1project('gdk-pixbuf', 'c',
2        version: '2.40.0',
3        license: 'LGPLv2.1+',
4        default_options: [
5          'buildtype=debugoptimized',
6          'warning_level=1',
7          'c_std=c99',
8        ],
9        meson_version: '>= 0.46.0')
10
11add_project_arguments([ '-D_POSIX_C_SOURCE=200809L', '-D_DEFAULT_SOURCE', '-D_XOPEN_SOURCE' ], language: 'c')
12
13cc = meson.get_compiler('c')
14host_system = host_machine.system()
15
16# Versioning
17gdk_pixbuf_version = meson.project_version()
18version_arr = gdk_pixbuf_version.split('.')
19gdk_pixbuf_version_major = version_arr[0].to_int()
20gdk_pixbuf_version_minor = version_arr[1].to_int()
21gdk_pixbuf_version_micro = version_arr[2].to_int()
22
23gdk_pixbuf_api_version = '2.0'
24gdk_pixbuf_binary_version = '2.10.0'
25
26gdk_pixbuf_api_name = '@0@-@1@'.format(meson.project_name(), gdk_pixbuf_api_version)
27
28if gdk_pixbuf_version_minor.is_odd()
29  gdk_pixbuf_interface_age = 0
30else
31  gdk_pixbuf_interface_age = gdk_pixbuf_version_micro
32endif
33
34gdk_pixbuf_binary_age = 100 * gdk_pixbuf_version_minor + gdk_pixbuf_version_micro
35
36# maintaining compatibility with the previous libtool versioning
37# current = binary - interface
38# revision = interface
39soversion = 0
40current = gdk_pixbuf_binary_age - gdk_pixbuf_interface_age
41revision = gdk_pixbuf_interface_age
42libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
43age = gdk_pixbuf_binary_age - gdk_pixbuf_interface_age
44current_minus_age = current - age
45darwin_versions = ['@0@'.format(current + 1), '@0@.@1@'.format(current + 1, gdk_pixbuf_interface_age)]
46
47# Paths
48gdk_pixbuf_prefix = get_option('prefix')
49gdk_pixbuf_libdir = join_paths(gdk_pixbuf_prefix, get_option('libdir'))
50gdk_pixbuf_bindir = join_paths(gdk_pixbuf_prefix, get_option('bindir'))
51gdk_pixbuf_includedir = join_paths(gdk_pixbuf_prefix, get_option('includedir'))
52gdk_pixbuf_datadir = join_paths(gdk_pixbuf_prefix, get_option('datadir'))
53gdk_pixbuf_mandir = join_paths(gdk_pixbuf_prefix, get_option('mandir'))
54gdk_pixbuf_localedir = join_paths(gdk_pixbuf_prefix, get_option('localedir'))
55gdk_pixbuf_libexecdir = join_paths(gdk_pixbuf_prefix, get_option('libexecdir'))
56gdk_pixbuf_loaderdir = join_paths(gdk_pixbuf_libdir, 'gdk-pixbuf-@0@/@1@/loaders'.format(gdk_pixbuf_api_version, gdk_pixbuf_binary_version))
57
58# Dependencies
59glib_req_version = '>= 2.38.0'
60glib_dep = dependency('glib-2.0', version: glib_req_version,
61                      fallback : ['glib', 'libglib_dep'])
62gobject_dep = dependency('gobject-2.0', version: glib_req_version,
63                         fallback : ['glib', 'libgobject_dep'])
64gmodule_dep = dependency('gmodule-no-export-2.0', version: glib_req_version,
65                         fallback : ['glib', 'libgmodule_dep'])
66gio_dep = dependency('gio-2.0', version: glib_req_version,
67                     fallback : ['glib', 'libgio_dep'])
68
69# Configurations
70gdk_pixbuf_conf = configuration_data()
71
72check_headers = [
73  'unistd.h',
74  'sys/resource.h',
75  'sys/time.h'
76]
77
78foreach h: check_headers
79  if cc.has_header(h)
80    gdk_pixbuf_conf.set('HAVE_' + h.underscorify().to_upper(), 1)
81  endif
82endforeach
83
84# Look for the math library first, since we use it to test for round() and lrint()
85mathlib_dep = cc.find_library('m', required: false)
86
87# XXX: Remove the checks for round() and lrint() once GDK-Pixbuf is declared C99
88if cc.has_function('round', dependencies: mathlib_dep)
89  gdk_pixbuf_conf.set('HAVE_ROUND', 1)
90endif
91
92if cc.has_function('lrint', dependencies: mathlib_dep)
93  gdk_pixbuf_conf.set('HAVE_LRINT', 1)
94endif
95
96if cc.has_function('bind_textdomain_codeset', prefix: '#include <libintl.h>')
97  gdk_pixbuf_conf.set('HAVE_BIND_TEXTDOMAIN_CODESET', 1)
98endif
99
100if cc.has_function('setrlimit', prefix: '#include <sys/time.h>\n#include <sys/resource.h>')
101  gdk_pixbuf_conf.set('HAVE_SETRLIMIT', 1)
102endif
103
104# We use links() because sigsetjmp() is often a macro hidden behind other macros
105gdk_pixbuf_conf.set('HAVE_SIGSETJMP',
106  cc.links('''#define _POSIX_SOURCE
107              #include <setjmp.h>
108              int main (void) {
109                sigjmp_buf env;
110                sigsetjmp (env, 0);
111                return 0;
112              }''', name: 'sigsetjmp'),
113)
114
115# Common compiler and linker flags
116common_cflags = []
117common_ldflags = []
118
119if cc.get_id() == 'msvc'
120  # For Visual Studio, just force-include msvc_reommended_pragmas.h
121  # so that we silence unwanted noise and track potential issues
122  test_cflags = []
123  add_project_arguments([ '-FImsvc_recommended_pragmas.h' ], language: 'c')
124elif cc.get_id() == 'gcc' or cc.get_id() == 'clang'
125  test_cflags = [
126    '-Wpointer-arith',
127    '-Wformat=2',
128    '-Wstrict-prototypes',
129    '-Wnested-externs',
130    '-Wold-style-definition',
131    '-Wdeclaration-after-statement',
132    '-Wunused',
133    '-Wcast-align',
134    '-Wmissing-noreturn',
135    '-Wmissing-format-attribute',
136    '-Wlogical-op',
137    '-fno-strict-aliasing',
138    '-Wno-int-conversion',
139    '-Wno-uninitialized',
140    '-Wno-discarded-qualifiers',
141    '-Werror=implicit',
142    '-Werror=nonnull',
143    '-Werror=init-self',
144    '-Werror=main',
145    '-Werror=missing-braces',
146    '-Werror=sequence-point',
147    '-Werror=return-type',
148    '-Werror=trigraphs',
149    '-Werror=array-bounds',
150    '-Werror=write-strings',
151    '-Werror=address',
152    '-Werror=int-to-pointer-cast',
153    '-Werror=pointer-to-int-cast',
154    '-Werror=empty-body',
155  ]
156
157  # Ensure we have the correct bit packing on Windows
158  if host_system == 'windows'
159    test_cflags += '-mms-bitfields'
160  endif
161else
162  test_cflags = []
163endif
164
165# Symbol visibility
166if get_option('default_library') != 'static'
167  if host_system == 'windows'
168    gdk_pixbuf_conf.set('DLL_EXPORT', true)
169    gdk_pixbuf_conf.set('_GDK_PIXBUF_EXTERN', '__declspec(dllexport) extern')
170    if cc.get_id() != 'msvc'
171      test_cflags += ['-fvisibility=hidden']
172    endif
173  else
174    gdk_pixbuf_conf.set('_GDK_PIXBUF_EXTERN', '__attribute__((visibility("default"))) extern')
175    test_cflags += ['-fvisibility=hidden']
176  endif
177endif
178
179common_cflags += cc.get_supported_arguments(test_cflags)
180
181if host_machine.system() == 'linux'
182  # Additional linker flags
183  test_ldflags = ['-Wl,-Bsymbolic', '-Wl,-z,relro', '-Wl,-z,now']
184  common_ldflags += cc.get_supported_link_arguments(test_ldflags)
185  gdk_pixbuf_conf.set('OS_LINUX', 1)
186endif
187
188if host_machine.system() == 'darwin'
189  # Maintain compatibility with autotools on macOS
190  common_ldflags += [ '-compatibility_version', darwin_versions[0], '-current_version', darwin_versions[1]]
191  gdk_pixbuf_conf.set('OS_DARWIN', 1)
192endif
193
194# On non-Windows/macOS systems we always required shared-mime-info and GIO
195# shared_mime_dep = []
196shared_mime_dep = []
197if get_option('gio_sniffing') and host_system != 'windows' and host_system != 'darwin'
198  shared_mime_dep += dependency('shared-mime-info')
199  gdk_pixbuf_conf.set('GDK_PIXBUF_USE_GIO_MIME', 1)
200endif
201
202# Check if medialib is available
203medialib_dep = cc.find_library('mlib', required: false)
204if medialib_dep.found()
205  if cc.has_function('mlib_ImageSetStruct', dependencies: medialib_dep)
206    gdk_pixbuf_conf.set('USE_MEDIALIB', 1)
207
208    if cc.has_function('mlib_VideoColorRGBint_to_BGRAint', dependencies: medialib_dep)
209      gdk_pixbuf_conf.set('USE_MEDIALIB25', 1)
210    endif
211  else
212    medialib_dep = []
213  endif
214endif
215
216gdk_pixbuf_deps = [ mathlib_dep, glib_dep, gobject_dep, gmodule_dep, gio_dep,
217                    shared_mime_dep, medialib_dep ]
218
219# Check if we can build shared modules
220if gmodule_dep.type_name() == 'pkgconfig'
221  build_modules = gmodule_dep.get_pkgconfig_variable('gmodule_supported') == 'true'
222else
223  build_modules = subproject('glib').get_variable('g_module_impl') != '0'
224endif
225gdk_pixbuf_conf.set('USE_GMODULE', build_modules)
226
227# Check which loaders should be built into gdk-pixbuf
228builtin_loaders = get_option('builtin_loaders').split(',')
229
230# If 'all' is specified for builtin_loaders, build all
231# buildable loaders into gdk-pixbuf
232builtin_all_loaders = false
233if builtin_loaders == [ 'all' ]
234  builtin_all_loaders = true
235endif
236
237# Loader dependencies
238enabled_loaders = []
239loaders_deps = []
240
241if get_option('png')
242  # We have a vast selection of libpng versions to choose from
243  foreach png: [ 'libpng16', 'libpng15', 'libpng14', 'libpng13', 'libpng12', 'libpng10' ]
244    if not enabled_loaders.contains('png')
245      png_dep = dependency(png, required: false)
246      if png_dep.found()
247        enabled_loaders += 'png'
248        loaders_deps += png_dep
249      endif
250    endif
251  endforeach
252
253  if not enabled_loaders.contains('png')
254    if cc.get_id() == 'msvc' and cc.has_header('png.h')
255      # MSVC: First look for the DLL + import .lib build of libpng,
256      # which is normally libpngxx.lib, when libpng's pkg-config can't
257      # be found, which is quite normal on MSVC.
258      foreach png: [ 'libpng16', 'libpng15', 'libpng14', 'libpng12', 'libpng13', 'libpng10' ]
259        if not enabled_loaders.contains('png')
260          png_dep = cc.find_library(png, required: false)
261          if png_dep.found()
262            enabled_loaders += 'png'
263            loaders_deps += png_dep
264          endif
265        endif
266      endforeach
267
268      # If we still can't find libpng, try looking for the static libpng.lib,
269      # which means we need to ensure we have the static zlib .lib as well
270      if not enabled_loaders.contains('png')
271        png_dep = cc.find_library('libpng', required: false)
272        zlib_dep = cc.find_library('zlib', required: false)
273        if png_dep.found() and zlib_dep.found()
274          enabled_loaders += 'png'
275          loaders_deps += [ png_dep, zlib_dep ]
276        endif
277      endif
278    endif
279
280    # Finally, look for the dependency in a fallback subproject if allowed by
281    # the --wrap-mode option. We don't directly call subproject() here because
282    # that will bypass --wrap-mode and cause issues for distro packagers.
283    # See: https://mesonbuild.com/Reference-manual.html#dependency
284    if not png_dep.found()
285      png_dep = dependency('', required: false, fallback: ['libpng', 'png_dep'])
286      if png_dep.found()
287        enabled_loaders += 'png'
288        loaders_deps += png_dep
289      endif
290    endif
291  endif
292endif
293
294# On Windows, check whether we are building the native Windows loaders
295# (it is an "all-or-nothing" option for BMP, EMF, GIF, ICO, JPEG, TIFF and WMF)
296# Note that we currently do not use the native Windows loaders to handle PNG and
297# JPEG2000 images
298if host_system == 'windows'
299  native_windows_loaders = get_option('native_windows_loaders')
300else
301  native_windows_loaders = false
302endif
303
304if native_windows_loaders
305  loaders_deps += cc.find_library('gdiplus')
306  loaders_deps += cc.find_library('ole32')
307  enabled_loaders += 'gdiplus'
308endif
309
310# Don't check and build the jpeg loader if native_windows_loaders is true
311if get_option('jpeg') and not native_windows_loaders
312  if cc.has_header('jpeglib.h')
313    jpeg_dep = cc.find_library('jpeg', required: false)
314    if cc.get_id() == 'msvc' and not jpeg_dep.found()
315      # The IJG JPEG library builds the .lib file as libjpeg.lib in its MSVC build system,
316      # so look for it as well when jpeg.lib cannot be found
317      jpeg_dep = cc.find_library('libjpeg', required: false)
318    endif
319    if jpeg_dep.found() and cc.has_function('jpeg_destroy_decompress', dependencies: jpeg_dep)
320      enabled_loaders += 'jpeg'
321      loaders_deps += jpeg_dep
322
323      gdk_pixbuf_conf.set('HAVE_PROGRESSIVE_JPEG',
324                          cc.has_function('jpeg_simple_progression',
325                                          dependencies: jpeg_dep))
326    endif
327  endif
328endif
329
330# Don't check and build the tiff loader if native_windows_loaders is true
331if get_option('tiff') and not native_windows_loaders
332  tiff_dep = dependency('libtiff-4', required: false)
333  if not tiff_dep.found()
334    # Fallback when no pkg-config file is found for libtiff on MSVC, which is quite normal
335    if cc.get_id() == 'msvc' and cc.has_header('tiff.h')
336      # First look for the DLL builds of libtiff, then the static builds
337      tiff_dep = cc.find_library('libtiff_i', required: false)
338
339      if not tiff_dep.found()
340        # For the static lib, zlib and libjpeg .lib's have been looked for first, and
341        # they are optional for libtiff
342        tiff_dep = cc.find_library('libtiff', required: false)
343      endif
344    endif
345  endif
346  if tiff_dep.found()
347    enabled_loaders += 'tiff'
348    loaders_deps += tiff_dep
349  endif
350endif
351
352jasper_extra_cflags = []
353
354if get_option('jasper')
355  has_jasper_header = false
356
357  if cc.get_id() == 'msvc'
358    # We must define JAS_WIN_MSVC_BUILD before including jasper/jasper.h on MSVC
359    jasper_msvc_macro = 'JAS_WIN_MSVC_BUILD'
360    has_jasper_header = cc.has_header('jasper/jasper.h', prefix: '#define @0@'.format(jasper_msvc_macro))
361    jasper_extra_cflags = [ '-D@0@'.format(jasper_msvc_macro) ]
362  else
363    has_jasper_header = cc.has_header('jasper/jasper.h')
364  endif
365
366  if has_jasper_header
367    jasper_dep = cc.find_library('jasper', required: false)
368    if not jasper_dep.found()
369      if cc.get_id() == 'msvc'
370        # on MSVC, we need to look for libjasper.lib if jasper.lib is not found,
371        # which corresponds to what libjasper's MSVC projects produce
372        jasper_dep = cc.find_library('libjasper', required: false)
373      endif
374    endif
375    if jasper_dep.found() and cc.has_function('jas_init', dependencies: jasper_dep)
376      enabled_loaders += 'jasper'
377      loaders_deps += jasper_dep
378    endif
379  endif
380endif
381
382# Determine whether we enable application bundle relocation support, and we use
383# this always on Windows
384if host_system == 'windows'
385  relocatable = true
386else
387  relocatable = get_option('relocatable')
388endif
389
390if relocatable
391  add_project_arguments([ '-DGDK_PIXBUF_RELOCATABLE' ], language: 'c')
392endif
393
394gdk_pixbuf_conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
395
396configure_file(output: 'config.h', configuration: gdk_pixbuf_conf)
397add_project_arguments([ '-DHAVE_CONFIG_H=1' ], language: 'c')
398
399root_inc = include_directories('.')
400
401# Auxiliary scripts
402gen_resources = find_program('build-aux/gen-resources.py')
403gen_installed_test = find_program('build-aux/gen-installed-test.py')
404gen_thumbnailer = find_program('build-aux/gen-thumbnailer.py')
405
406gnome = import('gnome')
407
408subdir('gdk-pixbuf')
409
410gdkpixbuf_xlib_inc = []
411if get_option('x11')
412  x11_dep = dependency('x11')
413  subdir('contrib/gdk-pixbuf-xlib')
414endif
415
416# i18n
417subdir('po')
418
419if not meson.is_cross_build()
420  subdir('thumbnailer')
421endif
422
423# Documentation
424subdir('docs')
425
426if not meson.is_cross_build()
427  # On Visual Studio, we don't normally have a shell interpreter, so use a .bat
428  if cc.get_id() == 'msvc'
429    meson.add_install_script('build-aux/post-install.bat',
430      gdk_pixbuf_bindir,
431      gdk_pixbuf_libdir,
432      gdk_pixbuf_binary_version,
433    )
434  else
435    meson.add_install_script('build-aux/post-install.sh',
436      gdk_pixbuf_bindir,
437      gdk_pixbuf_libdir,
438      gdk_pixbuf_binary_version,
439    )
440  endif
441endif
442
443summary = [
444  '',
445  'GDK-Pixbuf @0@'.format(meson.project_version()),
446  '==================',
447  '           prefix: @0@'.format(gdk_pixbuf_prefix),
448  '           libdir: @0@'.format(gdk_pixbuf_libdir),
449  '          datadir: @0@'.format(gdk_pixbuf_datadir),
450  '       libexecdir: @0@'.format(gdk_pixbuf_libexecdir),
451  '',
452  '  enabled loaders: @0@'.format(' '.join(enabled_loaders)),
453  '',
454  '    documentation: @0@'.format(get_option('docs')),
455  '        man pages: @0@'.format(get_option('man')),
456  '    introspection: @0@'.format(get_option('gir')),
457  '              x11: @0@'.format(get_option('x11')),
458  '  installed tests: @0@'.format(get_option('installed_tests')),
459  '      relocatable: @0@'.format(get_option('relocatable')),
460  '',
461]
462message('\n'.join(summary))
463