1project('gegl',
2  'c', 'cpp',
3  license: 'GPL3+',
4  version: '0.4.34',
5  # when meson version passes 0.53.0 remove alternate build summary
6  meson_version: '>=0.50.0',
7  default_options: [
8    'c_std=gnu11',
9    'cpp_std=gnu++14',
10    'buildtype=debugoptimized',
11  ],
12)
13
14# Making releases on the stable branch:
15#   micro_version += 1;
16#   interface_age += 1;
17#   binary_age += 1;
18# if any functions have been added,
19#    set interface_age to 0.
20# if backwards compatibility has been broken,
21#    set binary_age _and_ interface_age to 0.
22
23config    = configuration_data()
24
25pkgconfig = import('pkgconfig')
26i18n      = import('i18n')
27gnome     = import('gnome')
28python    = import('python').find_installation()
29
30cc        = meson.get_compiler('c')
31cpp       = meson.get_compiler('cpp')
32buildtype = get_option('buildtype')
33
34gegl_prefix     = get_option('prefix')
35gegl_gtk_docdir = gnome.gtkdoc_html_dir('gegl')
36gegl_libdir     = get_option('libdir')
37
38project_build_root = meson.current_build_dir()
39project_source_root = meson.current_source_dir()
40
41
42################################################################################
43# Dependency versions
44#
45# Core - required
46dep_ver = {
47  'babl'            : '>=0.1.78',
48  'glib'            : '>=2.44.0',
49  'json-glib'       : '>=1.0.0',
50  'poly2tri-c'      : '>=0.0.0',
51}
52
53# Core - optional
54dep_ver += {
55  'g-ir'            : '>=1.32.0',
56  'vapigen'         : '>=0.20.0',
57}
58
59# GEGL binary - optional
60dep_ver += {
61  'gexiv2'          : '>=0.0.0',
62  'libpng'          : '>=1.6.0',
63  'luajit'          : '>=2.0.4',
64  'mrg'             : '>=0.0.0',
65}
66
67# Operations - optional
68dep_ver += {
69  'gdk-pixbuf'      : '>=2.32.0',
70  'cairo'           : '>=1.12.2',
71  'pango'           : '>=1.38.0',
72  'pangocairo'      : '>=1.38.0',
73  'jasper'          : '>=1.900.1',
74  'lcms'            : '>=2.8',
75  'lensfun'         : '>=0.2.5',
76  'libjpeg'         : '>=1.0.0',
77  'libraw'          : '>=0.15.4',
78  'librsvg'         : '>=2.40.6',
79  'libspiro'        : '>=0.5.0',
80  'libtiff'         : '>=4.0.0',
81  'libv4l1'         : '>=1.0.1',
82  'libv4l2'         : '>=1.0.1',
83  'libwebp'         : '>=0.5.0',
84  'maxflow'         : '>=3.0.4',
85  'openexr'         : '>=1.6.1',
86  'poppler'         : '>=0.71.0',
87  'sdl1'            : '>=1.2.0',
88  'sdl2'            : '>=2.0.5',
89  'libavcodec'      : '>=55.69.100',
90  'libavformat'     : '>=55.48.100',
91  'libavutil'       : '>=55.92.100',
92  'libswscale'      : '>=2.6.100',
93}
94
95# Tests (runtime) - optional
96dep_ver += {
97  'pygobject'       : '>=3.2.0',
98}
99
100
101################################################################################
102# Project infos
103
104version = meson.project_version()
105array_version = version.split('.')
106major_version = array_version[0].to_int()
107minor_version = array_version[1].to_int()
108micro_version = array_version[2].to_int()
109
110api_version = '@0@.@1@'.format(major_version, minor_version)
111api_name    = meson.project_name() + '-' + api_version
112gettext_package = api_name
113
114stability_version_number = (major_version != 0 ? minor_version : micro_version)
115stable = (stability_version_number % 2 == 0)
116
117config.set        ('GEGL_MAJOR_VERSION',  '@0@'.format(major_version))
118config.set        ('GEGL_MINOR_VERSION',  '@0@'.format(minor_version))
119config.set        ('GEGL_MICRO_VERSION',  '@0@'.format(micro_version))
120config.set        ('GEGL_UNSTABLE',       not stable)
121
122config.set_quoted ('GEGL_LIBRARY',        '@0@'.format(api_name))
123config.set_quoted ('GETTEXT_PACKAGE',     '@0@'.format(gettext_package))
124
125# Libtool versionning
126interface_age = 1
127
128binary_age = 100 * minor_version + micro_version
129lt_current = binary_age - interface_age
130so_version  = '@0@.@1@.@2@'.format(0, lt_current, interface_age)
131
132################################################################################
133# Host system detection
134
135host_os = host_machine.system()
136os_win32  = host_os.contains('mingw') or host_os.contains('windows')
137os_android= host_os.contains('android')
138os_osx    = host_os.contains('darwin')
139
140if os_osx and cc.get_id() != 'clang'
141  error('You should use Clang on OSx.')
142endif
143
144host_cpu_family = host_machine.cpu_family()
145if   host_cpu_family == 'x86'
146  have_x86 = true
147  config.set10('ARCH_X86',    true)
148elif host_cpu_family == 'x86_64'
149  have_x86 = true
150  config.set10('ARCH_X86',    true)
151  config.set10('ARCH_X86_64', true)
152elif host_cpu_family == 'ppc'
153  have_ppc = true
154  config.set10('ARCH_PPC',    true)
155elif host_cpu_family == 'ppc64'
156  have_ppc = true
157  config.set10('ARCH_PPC',    true)
158  config.set10('ARCH_PPC64',  true)
159endif
160
161# Only try to run compiled programs if native compile or cross-compile
162# and have exe wrapper. If we don't need a wrapper (e.g. 32 bit build in
163# 64-bit environment) then set proprty has_exe_wrapper=true in cross
164# file
165can_run_host_binaries = meson.has_exe_wrapper()
166
167
168################################################################################
169# Compiler arguments
170
171cflags_common = []
172cflags_c      = []
173cflags_cpp    = []
174
175cflags_common += '-DHAVE_CONFIG_H'
176
177if buildtype == 'debugoptimized' or buildtype == 'release'
178  cflags_common += '-Ofast'
179endif
180
181if buildtype == 'debugoptimized' or buildtype == 'debug'
182  cflags_common += '-DGEGL_ENABLE_DEBUG'
183endif
184
185cflags_common += [
186  '-Winit-self',
187  '-Wmissing-declarations',
188  '-Wpointer-arith',
189  '-Wno-deprecated-declarations',
190]
191cflags_c = [
192  '-Wmissing-prototypes',
193  '-Wold-style-definition',
194]
195
196if os_win32
197  cflags_common += '-D_FILE_OFFSET_BITS=64'
198endif
199
200cflags_c   = cflags_common + cflags_c
201cflags_cpp = cflags_common + cflags_cpp
202
203add_project_arguments(cc.get_supported_arguments(cflags_c), language: 'c')
204add_project_arguments(cpp.get_supported_arguments(cflags_cpp), language: 'cpp')
205
206################################################################################
207# Build Utilities
208
209env               = find_program('env')
210
211asciidoc          = find_program('asciidoc',
212                     required: false, native: true)
213dot               = find_program('dot',
214                     required: false, native: true)
215gtkdoc_scan       = find_program('gtkdoc-scan',
216                     required: false, native: true)
217source_highlight  = find_program('source-highlight',
218                     required: false, native: true)
219w3m               = find_program('w3m',
220                     required: false, native: true)
221
222################################################################################
223# Required Dependencies
224
225config.set('HAVE_UNISTD_H',    cc.has_header('unistd.h'))
226config.set('HAVE_EXECINFO_H',  cc.has_header('execinfo.h'))
227config.set('HAVE_FSYNC',       cc.has_function('fsync'))
228config.set('HAVE_MALLOC_TRIM', cc.has_function('malloc_trim'))
229config.set('HAVE_STRPTIME',    cc.has_function('strptime'))
230
231math    = cc.find_library('m',  required: false)
232libdl   = cc.find_library('dl', required : false)
233thread  = dependency('threads')
234
235babl      = dependency('babl',        version: dep_ver.get('babl'))
236glib      = dependency('glib-2.0',    version: dep_ver.get('glib'))
237gobject   = dependency('gobject-2.0', version: dep_ver.get('glib'))
238gmodule   = dependency('gmodule-2.0', version: dep_ver.get('glib'))
239gthread   = dependency('gthread-2.0', version: dep_ver.get('glib'))
240gio_os    = os_win32 ? 'gio-windows-2.0' : 'gio-unix-2.0'
241gio       = [
242            dependency('gio-2.0',     version: dep_ver.get('glib')),
243            dependency(gio_os,        version: dep_ver.get('glib')),
244]
245json_glib = dependency('json-glib-1.0',
246  version: dep_ver.get('json-glib')
247)
248libjpeg   = dependency('libjpeg',     version: dep_ver.get('libjpeg'))
249libpng    = dependency('libpng',      version: dep_ver.get('libpng'))
250
251# Required libraries eventually provided in subprojects/ subdir
252poly2tri_c = dependency('poly2tri-c',
253  version:  dep_ver.get('poly2tri-c'),
254  fallback: ['poly2tri-c', 'poly2tri_c'],
255  required: false,
256)
257
258libnsgif = dependency('libnsgif',
259  fallback: ['libnsgif', 'libnsgif'],
260)
261
262################################################################################
263# Optionnal Dependencies
264
265# GEGL library
266if get_option('introspection') != 'false'
267  g_ir = dependency('gobject-introspection-1.0',
268    version:  dep_ver.get('g-ir'),
269    required: get_option('introspection') == 'true' ? true : false,
270  )
271else
272  g_ir = disabler()
273endif
274if g_ir.found()
275  vapigen   = dependency('vapigen',
276    version: dep_ver.get('vapigen'),
277    required: get_option('vapigen')
278  )
279else
280  vapigen = disabler()
281endif
282
283# GEGL binary
284gexiv2    = dependency('gexiv2',
285  version: dep_ver.get('gexiv2'),
286  required: get_option('gexiv2')
287)
288config.set('HAVE_GEXIV2', gexiv2.found())
289lua       = dependency('luajit',
290  version: dep_ver.get('luajit'),
291  required: get_option('lua')
292)
293config.set('HAVE_LUA', lua.found())
294mrg       = dependency('mrg',
295  version: dep_ver.get('mrg'),
296  required: get_option('mrg')
297)
298config.set('HAVE_MRG', mrg.found())
299
300# Operations
301gdk_pixbuf= dependency('gdk-pixbuf-2.0',
302  version: dep_ver.get('gdk-pixbuf'),
303  required: get_option('gdk-pixbuf')
304)
305cairo     = dependency('cairo',
306  version: dep_ver.get('cairo'),
307  required: get_option('cairo')
308)
309pango     = dependency('pango',
310  version: dep_ver.get('pango'),
311  required: get_option('pango')
312)
313pangocairo = dependency('pangocairo',
314  version: dep_ver.get('pangocairo'),
315  required: get_option('pangocairo')
316)
317
318jasper    = dependency('jasper',
319  version: dep_ver.get('jasper'),
320  required: get_option('jasper')
321)
322lcms      = dependency('lcms2',
323  version: dep_ver.get('lcms'),
324  required: get_option('lcms')
325)
326lensfun   = dependency('lensfun',
327  version: dep_ver.get('lensfun'),
328  required: get_option('lensfun')
329)
330libraw    = dependency('libraw',
331  version: dep_ver.get('libraw'),
332  required: get_option('libraw')
333)
334librsvg   = dependency('librsvg-2.0',
335  version: dep_ver.get('librsvg'),
336  required: get_option('librsvg')
337)
338libspiro  = dependency('libspiro',
339  version: dep_ver.get('libspiro'),
340  required: get_option('libspiro')
341)
342libtiff   = dependency('libtiff-4',
343  version: dep_ver.get('libtiff'),
344  required: get_option('libtiff')
345)
346libv4l1   = dependency('libv4l1',
347  version: dep_ver.get('libv4l1'),
348  required: get_option('libv4l')
349)
350libv4l2   = dependency('libv4l2',
351  version: dep_ver.get('libv4l2'),
352  required: get_option('libv4l2')
353)
354libwebp   = dependency('libwebp',
355  version: dep_ver.get('libwebp'),
356  required: get_option('webp')
357)
358maxflow   = dependency('maxflow',
359  version: dep_ver.get('maxflow'),
360  required: get_option('maxflow')
361)
362openexr   = dependency('OpenEXR',
363  version: dep_ver.get('openexr'),
364  required: get_option('openexr')
365)
366poppler = dependency('poppler-glib',
367  version: dep_ver.get('poppler'),
368  required: get_option('poppler')
369)
370sdl1      = dependency('sdl',
371  version: dep_ver.get('sdl1'),
372  required: get_option('sdl1')
373)
374sdl2      = dependency('sdl2',
375  version: dep_ver.get('sdl2'),
376  required: get_option('sdl2')
377)
378
379# AV libs
380libavcodec = dependency('libavcodec',
381  version: dep_ver.get('libavcodec'),
382  required: get_option('libav')
383)
384libavformat = dependency('libavformat',
385  version: dep_ver.get('libavformat'),
386  required: get_option('libav')
387)
388libavutil = dependency('libavutil',
389  version: dep_ver.get('libavutil'),
390  required: get_option('libav')
391)
392libswscale = dependency('libswscale',
393  version: dep_ver.get('libswscale'),
394  required: get_option('libav')
395)
396avlibs_found = (
397  libavcodec.found() and
398  libavformat.found() and
399  libavutil.found() and
400  libswscale.found()
401)
402avlibs = avlibs_found ? [libavcodec, libavformat, libavutil, libswscale] : []
403
404# libumfpack
405libumfpack = cc.find_library('umfpack', required: get_option('umfpack'))
406if libumfpack.found()
407  have_umfpack = cc.has_header('umfpack.h')
408  have_ss_umfpack = cc.has_header_symbol(
409    'suitesparse/umfpack.h',
410    'umfpack_dl_solve'
411  )
412
413  if not (have_umfpack or have_ss_umfpack)
414    if get_option('umfpack').auto()
415      libumfpack = dependency('', required: false)
416    else
417      error('UmfPack library found but not headers.')
418    endif
419  endif
420  config.set('HAVE_UMFPACK_H', have_umfpack)
421  config.set('HAVE_SUITESPARSE_UMFPACK_H', have_ss_umfpack)
422endif
423
424# Tests
425if g_ir.found()
426  pygobject3 = dependency('pygobject-3.0',
427    version: dep_ver.get('pygobject'),
428    required: get_option('pygobject')
429  )
430else
431  pygobject3 = disabler()
432endif
433
434################################################################################
435# Build flags
436
437# Docs
438build_docs = true
439if get_option('docs') == 'auto'
440  if meson.is_cross_build()
441    build_docs = false
442    message('configure with -Ddocs=true to cross-build docs')
443  elif not asciidoc.found()
444    build_docs = false
445  endif
446elif get_option('docs') == 'false'
447  build_docs = false
448elif not asciidoc.found()
449  build_docs = false
450  warning('asciidoc is required to build website')
451endif
452build_reference = get_option('gtk-doc')
453
454
455#########################################################################
456# Subdirs
457
458configure_file(
459  output: 'config.h',
460  configuration: config
461)
462
463rootInclude = include_directories('.')
464
465argvs_extract = find_program('tools/argvs_extract.sh')
466
467subdir('libs/rgbe')
468subdir('opencl')
469subdir('gegl')
470subdir('libs/npd')
471subdir('seamless-clone')
472subdir('bin')
473subdir('tools')
474subdir('operations')
475subdir('examples')
476subdir('tests')
477subdir('perf')
478subdir('po')
479subdir('docs')
480
481
482if w3m.found()
483  # Create NEWS file from html file
484  if is_variable('news_html')
485    custom_target('NEWS',
486      input: news_html,
487      output: 'NEWS',
488      command: [
489        w3m,
490        '-cols', '72',
491        '-dump',
492        '@INPUT@',
493      ],
494      capture: true,
495      build_by_default: true
496    )
497  endif
498
499  if is_variable('index_html')
500    # Create README file from html file
501    custom_target('README',
502      input: index_html,
503      output: 'README',
504      command: [
505        w3m,
506        '-cols', '72',
507        '-dump',
508        '@INPUT@',
509      ],
510      capture: true,
511      build_by_default: true
512    )
513  endif
514endif
515
516# pkg-config file
517pkgconfig.generate(filebase: 'gegl-' + api_version,
518  name: 'GEGL',
519  description: 'Generic Graphics Library',
520  version: meson.project_version(),
521  variables: 'pluginsdir=' + '${prefix}' / get_option('libdir') / api_name,
522  requires: [
523    gobject,
524    gmodule,
525    gio,
526    json_glib,
527    babl,
528  ],
529  libraries: [
530    gegl_lib,
531    gegl_npd_lib,
532    math,
533  ],
534  subdirs: api_name,
535)
536
537
538################################################################################
539# Build summary
540
541# workaround for some old build systems building GIMP 2.10
542if meson.version().version_compare('>=0.53.0')
543  summary(
544    {
545      'prefix'        : gegl_prefix,
546      'libdir'        : gegl_libdir,
547    }, section: 'Directories'
548  )
549  summary(
550    {
551      'Reference'       : build_reference,
552      'Docs'            : build_docs,
553    }, section: 'GEGL docs'
554  )
555  summary(
556    {
557      'Build workshop'    : get_option('workshop'),
558      'Introspection'     : g_ir.found(),
559      'Vala support'      : vapigen.found(),
560    }, section: 'Optional features'
561  )
562  summary(
563    {
564      'asciidoc'          : asciidoc.found(),
565      'dot'               : dot.found(),
566      'pygobject'         : pygobject3.found(),
567      'source-highlight'  : source_highlight.found(),
568      'w3m'               : w3m.found(),
569    }, section: 'Optional build utilities'
570  )
571  summary(
572    {
573      'avlibs'            : avlibs_found,
574      'Cairo'             : cairo.found(),
575      'GDKPixbuf'         : gdk_pixbuf.found(),
576      'gexiv2'            : gexiv2.found(),
577      'Jasper'            : jasper.found(),
578      'lcms'              : lcms.found(),
579      'libnsgif'          : libnsgif.found(),
580      'libraw'            : libraw.found(),
581      'Luajit'            : lua.found(),
582      'maxflow'           : maxflow.found(),
583      'mrg'               : mrg.found(),
584      'Pango'             : pango.found(),
585      'pangocairo'        : pangocairo.found(),
586      'poly2tri-c'        : poly2tri_c.found(),
587      'poppler'           : poppler.found(),
588      'OpenEXR'           : openexr.found(),
589      'rsvg'              : librsvg.found(),
590      'SDL1'              : sdl1.found(),
591      'SDL2'              : sdl2.found(),
592      'spiro'             : libspiro.found(),
593      'TIFF'              : libtiff.found(),
594      'umfpack'           : libumfpack.found(),
595      'V4L'               : libv4l1.found(),
596      'V4L2'              : libv4l2.found(),
597      'webp'              : libwebp.found(),
598    }, section: 'Optional dependencies'
599  )
600else
601  message('\n'.join(['',
602  'Building GEGL with prefix=@0@'.format(get_option('prefix')),
603  '',
604  'GEGL docs:',
605  '  Reference:         @0@'.format(build_reference),
606  '  Docs:              @0@'.format(build_docs),
607  '',
608  'Optional features:',
609  '  Build workshop:    @0@'.format(get_option('workshop')),
610  '  Introspection:     @0@'.format(g_ir.found()),
611  '  Vala support:      @0@'.format(vapigen.found()),
612  '',
613  'Optional build utilities:',
614  '  asciidoc:          @0@'.format(asciidoc.found()),
615  '  dot:               @0@'.format(dot.found()),
616  '  pygobject:         @0@'.format(pygobject3.found()),
617  '  source-highlight:  @0@'.format(source_highlight.found()),
618  '  w3m:               @0@'.format(w3m.found()),
619  '',
620  'Optional dependencies:',
621  '  av libs:           @0@'.format(avlibs_found),
622  '  Cairo:             @0@'.format(cairo.found()),
623  '  GDKPixbuf:         @0@'.format(gdk_pixbuf.found()),
624  '  gexiv2:            @0@'.format(gexiv2.found()),
625  '  Jasper:            @0@'.format(jasper.found()),
626  '  lcms:              @0@'.format(lcms.found()),
627  '  libnsgif:          @0@'.format(libnsgif.found()),
628  '  libraw:            @0@'.format(libraw.found()),
629  '  Luajit:            @0@'.format(lua.found()),
630  '  maxflow:           @0@'.format(maxflow.found()),
631  '  mrg:               @0@'.format(mrg.found()),
632  '  Pango:             @0@'.format(pango.found()),
633  '  pangocairo:        @0@'.format(pangocairo.found()),
634  '  poly2tri-c:        @0@ (@1@)'.format(poly2tri_c.found(),poly2tri_c.type_name()),
635  '  poppler:           @0@'.format(poppler.found()),
636  '  OpenEXR:           @0@'.format(openexr.found()),
637  '  rsvg:              @0@'.format(librsvg.found()),
638  '  SDL1:              @0@'.format(sdl1.found()),
639  '  SDL2:              @0@'.format(sdl2.found()),
640  '  spiro:             @0@'.format(libspiro.found()),
641  '  TIFF               @0@'.format(libtiff.found()),
642  '  umfpack:           @0@'.format(libumfpack.found()),
643  '  V4L:               @0@'.format(libv4l1.found()),
644  '  V4L2:              @0@'.format(libv4l2.found()),
645  '  webp:              @0@'.format(libwebp.found()),
646  '']))
647endif
648