meson.build 16.3 KB
Newer Older
Patrick Griffis's avatar
Patrick Griffis committed
1
cairo_conf = configuration_data()
2
3
if get_option('cairo_libname') != ''
  cairo_library_name = get_option('cairo_libname')
4
elif host_machine.system() == 'windows'
5
6
7
8
9
  if cc.get_id() == 'msvc'
    cairo_library_name = 'cairo-gobject.dll'
  else
    cairo_library_name = 'libcairo-gobject-2.dll'
  endif
Patrick Griffis's avatar
Patrick Griffis committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
elif host_machine.system() == 'darwin'
  cairo_library_name = 'libcairo-gobject.2.dylib'
else
  cairo_library_name = 'libcairo-gobject.so.2'
endif

cairo_conf.set('CAIRO_SHARED_LIBRARY', cairo_library_name)
cairo_conf.set('CAIRO_GIR_PACKAGE', 'cairo-gobject')

cairo_gir = configure_file(
  input: 'cairo-1.0.gir.in',
  output: 'cairo-1.0.gir',
  configuration: cairo_conf,
)

gir_files = [
  cairo_gir,
  'DBus-1.0.gir',
  'DBusGLib-1.0.gir',
  'fontconfig-2.0.gir',
  'freetype2-2.0.gir',
  'GL-1.0.gir',
  'libxml2-2.0.gir',
Matthew Waters's avatar
Matthew Waters committed
33
  'Vulkan-1.0.gir',
Patrick Griffis's avatar
Patrick Griffis committed
34
35
36
37
38
39
40
41
42
43
  'xft-2.0.gir',
  'xlib-2.0.gir',
  'xfixes-4.0.gir',
  'xrandr-1.3.gir',
  'win32-1.0.gir',
]

typelibdir = join_paths(get_option('libdir'), 'girepository-1.0')
install_data(gir_files, install_dir: girdir)

44
45
46
47
48
49
50
51
scanner_command = [
  find_program('g-ir-scanner', native: true),
  '--output=@OUTPUT@',
  '--no-libtool',
  '--quiet',
  '--reparse-validate',
  '--add-include-path', join_paths(meson.current_build_dir()),
  '--add-include-path', join_paths(meson.current_source_dir()),
52
]
Patrick Griffis's avatar
Patrick Griffis committed
53

54
55
dep_type = glib_dep.type_name()
if dep_type == 'internal'
56
57
58
59
60
  # XXX: Instead of hard-coding the subproject directory, we should use
  # gnome.generate_gir() because that will take care of dependencies, include
  # paths, library paths, and more that we now have to handle manually when
  # building with subprojects.
  subprojdir = 'subprojects'
61
62
63
64
65
66
  scanner_command += [
    '--extra-library=glib-2.0',
    '--extra-library=gmodule-2.0',
    '--extra-library=gobject-2.0',
    '--extra-library=gio-2.0',
  ]
67
68
endif

69
70
if get_option('gi_cross_binary_wrapper') != ''
  scanner_command += ['--use-binary-wrapper=' + get_option('gi_cross_binary_wrapper')]
71
endif
72
73
if get_option('gi_cross_ldd_wrapper') != ''
  scanner_command += ['--use-ldd-wrapper=' + get_option('gi_cross_ldd_wrapper')]
74
endif
75
76
77
78
# Take a glob and print to newlines
globber = '''
from glob import glob

79
80
81
82
# Sort the glob for stable results. Also ensures that gmarshal.h is not
# #include-ed by scannerparser.y first because it does not include glib.h
# itself, which leaves several defines unresolved.
for f in sorted(glob('@0@')):
83
84
85
  print(f)
'''

Patrick Griffis's avatar
Patrick Griffis committed
86
# GLib
87
glib_files = []
88
89
90
91
92
93
94
95
96
97
glib_command = scanner_command + [
  '--identifier-prefix=G',
  '--symbol-prefix=g',
  '--symbol-prefix=glib',
  '--c-include=glib.h',
  '--namespace=GLib',
  '--nsversion=2.0',
  '--library=glib-2.0',
  '--library=gobject-2.0',
]
Patrick Griffis's avatar
Patrick Griffis committed
98

99
100
if dep_type == 'pkgconfig'
  glib_command += ['--external-library', '--pkg=glib-2.0']
101
102
  glib_libdir = get_option('gi_cross_pkgconfig_sysroot_path') + glib_dep.get_variable(pkgconfig: 'libdir')
  glib_incdir = get_option('gi_cross_pkgconfig_sysroot_path') + join_paths(glib_dep.get_variable(pkgconfig: 'includedir'), 'glib-2.0')
103
104
105
106
107
108
109
  glib_libincdir = join_paths(glib_libdir, 'glib-2.0', 'include')
  glib_files += join_paths(glib_incdir, 'gobject', 'glib-types.h')
  glib_files += join_paths(glib_libincdir, 'glibconfig.h')
  if giounix_dep.found()
    glib_files += join_paths(glib_incdir, 'glib-unix.h')
  endif
  # Parse glob to get installed header list
110
  ret = run_command(python, '-c', globber.format(join_paths(glib_incdir, 'glib', '*.h')))
111
112
113
114
115
  if ret.returncode() != 0
    error('Failed to get glib header list')
  endif
  glib_headers = ret.stdout().strip().split('\n')
  # Get a list of all source files
116
  glib_srcdir = get_option('glib_src_dir')
117
  if glib_srcdir != ''
118
    ret = run_command(python, '-c', globber.format(join_paths(glib_srcdir, 'glib', '*.c')))
119
120
121
122
123
124
    if ret.returncode() != 0
      error('Failed to get glib source list')
    endif
    glib_files += ret.stdout().strip().split('\n')
  endif
  glib_includes = ['-I' + glib_incdir, '-I' + glib_libincdir]
125
  glib_gir_dep = []
126
elif dep_type == 'internal'
127
128
129
130
131
132
  # XXX: This is a pile of hacks to allow gobject-introspection to parse the
  #      GLib source files when GLib is used as a subproject
  #      Assumes that the builddir layout is 'mirror'
  #      Assumes the location of the glib subproject dir
  #      We should add API to meson to get a specific file from a specific
  #      subproject
133
134
  # We know exactly what headers will be installed, so just fetch that
  glib_subproject = subproject('glib')
135

136
137
  glibproj_sourcedir = join_paths(meson.project_source_root(), subprojdir, 'glib')
  glibproj_builddir = join_paths(meson.project_build_root(), subprojdir, 'glib')
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

  glib_files += join_paths(glibproj_sourcedir, 'gobject', 'glib-types.h')

  # Generated files, relative to the build directory
  glib_files += [
    join_paths(glibproj_builddir, 'glib', 'glibconfig.h'),
    glib_subproject.get_variable('glib_enumtypes_h'),
  ]

  if giounix_dep.found()
    glib_files += [
      join_paths(glibproj_sourcedir, 'glib', 'glib-unix.h'),
    ]
  endif

153
154
  glib_headers = glib_subproject.get_variable('glib_sub_headers')
  glib_files += glib_subproject.get_variable('glib_sources')
155

156
  # XXX: Assumes that the builddir layout is 'mirror'
157
158
159
160
161
162
163
164
165
166
167
  glib_libdir = join_paths(glibproj_builddir, 'glib')
  gobject_libdir = join_paths(glibproj_builddir, 'gobject')
  gmodule_libdir = join_paths(glibproj_builddir, 'gmodule')
  gio_libdir = join_paths(glibproj_builddir, 'gio')

  glib_libpaths = [
    '-L' + glib_libdir,
    '-L' + gobject_libdir,
    '-L' + gmodule_libdir,
    '-L' + gio_libdir,
  ]
168
  # Includes that will be used to compile the scanner executable
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  glib_incdir = join_paths(glibproj_sourcedir, 'glib')
  gobject_incdir = join_paths(glibproj_sourcedir, 'gobject')
  gmodule_incdir = join_paths(glibproj_sourcedir, 'gmodule')
  gio_incdir = join_paths(glibproj_sourcedir, 'gio')

  glib_includes = [
    '-I' + glibproj_sourcedir,
    '-I' + glibproj_builddir,
    '-I' + glib_libdir,
    '-I' + glib_incdir,
    '-I' + gobject_incdir,
    '-I' + gmodule_incdir,
    '-I' + gio_incdir,
  ]

184
185
186
  # XXX: We need include paths to all glib dependencies too. We assume that the
  # dependencies are only libffi and proxy-libintl, and that they are used as
  # subprojects. In the worst case we add paths to non-existent directories.
187
  ffi_incdir = join_paths(meson.project_build_root(), subprojdir, 'libffi', 'include')
188
  glib_includes += ['-I' + ffi_incdir]
189
  intl_incdir = join_paths(meson.project_source_root(), subprojdir, 'proxy-libintl')
190
  glib_includes += ['-I' + intl_incdir]
191

192
193
  ffi_libdir = join_paths(meson.project_build_root(), subprojdir, 'libffi', 'src')
  intl_libdir = join_paths(meson.project_build_root(), subprojdir, 'proxy-libintl')
194
195
196
197
  glib_libpaths = [
    '-L' + ffi_libdir,
    '-L' + intl_libdir,
  ] + glib_libpaths
198

199
  glib_command += ['--pkg-export=glib-2.0']
200
201
  glib_command += glib_libpaths

202
  glib_gir_dep = glib_subproject.get_variable('libglib')
203
204
else
  error('Unknown glib dependency type: ' + dep_type)
Patrick Griffis's avatar
Patrick Griffis committed
205
206
endif

207
208
209
210
211
212
foreach h : glib_headers
  hstr = '@0@'.format(h)
  if not hstr.endswith('autocleanups.h')
    glib_files += h
  endif
endforeach
Patrick Griffis's avatar
Patrick Griffis committed
213

214
215
216
217
218
# NOTE: Always add this last so that we prefer the annotations in the sources
# (if they are available) since it contains 'backup' annotations that can be
# out of date.
glib_files += files('glib-2.0.c')

219
220
221
222
223
224
225
226
227
gir_giscanner_pymod = []
gir_giscanner_built_files = []
if not get_option('gi_cross_use_prebuilt_gi')
  # The right thing to do is just make these dependencies of the
  # `configure_file` python executable, but that isn't yet supported.
  gir_giscanner_pymod = giscanner_pymod
  gir_giscanner_built_files = giscanner_built_files
endif

Patrick Griffis's avatar
Patrick Griffis committed
228
glib_gir = custom_target('gir-glib',
229
  input: glib_files,
Patrick Griffis's avatar
Patrick Griffis committed
230
  output: 'GLib-2.0.gir',
231
  depends: [gir_giscanner_pymod, glib_gir_dep],
232
  depend_files: gir_giscanner_built_files,
Patrick Griffis's avatar
Patrick Griffis committed
233
234
  install: true,
  install_dir: girdir,
235
  command: glib_command + [
236
    '--cflags-begin'] + glib_includes + extra_giscanner_cflags + [
Patrick Griffis's avatar
Patrick Griffis committed
237
238
239
240
    '-DGLIB_COMPILATION',
    '-D__G_I18N_LIB_H__',
    '-DGETTEXT_PACKAGE=Dummy',
    '--cflags-end',
241
    '@INPUT@',
Patrick Griffis's avatar
Patrick Griffis committed
242
243
244
245
246
247
  ]
)

gir_files += glib_gir

# GObject
248
gobject_files = []
249
250
251
252
253
254
255
256
257
258
259
gobject_command = scanner_command + [
  '--identifier-prefix=G',
  '--c-include=glib-object.h',
  '--namespace=GObject',
  '--nsversion=2.0',
  '--library=gobject-2.0',
]

if dep_type == 'pkgconfig'
  gobject_command += ['--external-library', '--pkg=gobject-2.0']
  # Get the installed header list
260
  ret = run_command(python, '-c', globber.format(join_paths(glib_incdir, 'gobject', '*.h')))
261
262
263
264
265
  if ret.returncode() != 0
    error('Failed to get gobject header list')
  endif
  gobject_headers = ret.stdout().strip().split('\n')
  if glib_srcdir != ''
266
    ret = run_command(python, '-c', globber.format(join_paths(glib_srcdir, 'gobject', '*.c')))
267
268
269
270
271
    if ret.returncode() != 0
      error('Failed to get gobject source list')
    endif
    gobject_files += ret.stdout().strip().split('\n')
  endif
272
  gobject_gir_dep = []
273
274
275
else
  gobject_command += ['--pkg-export=gobject-2.0']
  gobject_headers = glib_subproject.get_variable('gobject_install_headers')
276
277
278
  gobject_files += [
    glib_subproject.get_variable('gobject_sources'),
  ]
279
  gobject_command += glib_libpaths
280
  gobject_gir_dep = glib_subproject.get_variable('libgobject')
Patrick Griffis's avatar
Patrick Griffis committed
281
282
endif

283
284
foreach h : gobject_headers
  hstr = '@0@'.format(h)
285
  if not hstr.endswith('autocleanups.h') and not hstr.endswith('glib-types.h') and not hstr.endswith('gvaluecollector.h') and not hstr.endswith('glib-enumtypes.h')
286
287
288
    gobject_files += h
  endif
endforeach
Patrick Griffis's avatar
Patrick Griffis committed
289

290
291
292
293
294
# NOTE: Always add this last so that we prefer the annotations in the sources
# (if they are available) since it contains 'backup' annotations that can be
# out of date.
gobject_files += files('gobject-2.0.c')

Patrick Griffis's avatar
Patrick Griffis committed
295
gobject_gir = custom_target('gir-gobject',
296
  input: gobject_files,
Patrick Griffis's avatar
Patrick Griffis committed
297
  output: 'GObject-2.0.gir',
298
  depends: [glib_gir, gir_giscanner_pymod, gobject_gir_dep],
299
  depend_files: gir_giscanner_built_files,
Patrick Griffis's avatar
Patrick Griffis committed
300
301
  install: true,
  install_dir: girdir,
302
  command: gobject_command + [
Patrick Griffis's avatar
Patrick Griffis committed
303
    '--include-uninstalled=' + glib_gir.full_path(),
304
    '--cflags-begin'] + glib_includes + extra_giscanner_cflags + [
Patrick Griffis's avatar
Patrick Griffis committed
305
306
    '-DGOBJECT_COMPILATION',
    '--cflags-end',
307
    '@INPUT@',
Patrick Griffis's avatar
Patrick Griffis committed
308
309
310
311
312
313
  ]
)

gir_files += gobject_gir

# GModule
314
gmodule_files = []
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
gmodule_command = scanner_command + [
  '--identifier-prefix=G',
  '--symbol-prefix=g',
  '--c-include=gmodule.h',
  '--namespace=GModule',
  '--nsversion=2.0',
  '--library=gmodule-2.0',
]

if dep_type == 'pkgconfig'
  gmodule_command += ['--external-library', '--pkg=gmodule-2.0']
  gmodule_files += join_paths(glib_incdir, 'gmodule.h')
  if glib_srcdir != ''
    gmodule_files += join_paths(glib_srcdir, 'gmodule', 'gmodule.c')
  endif
330
  gmodule_gir_dep = []
331
332
333
else
  gmodule_command += ['--pkg-export=gmodule-2.0']
  gmodule_command += glib_libpaths
334
335
336
337
338
339
  gmodule_files += [
    join_paths(glibproj_sourcedir, 'gmodule', 'gmodule.h'),
    join_paths(glibproj_sourcedir, 'gmodule', 'gmodule.c'),
    glib_subproject.get_variable('gmoduleconf_h'),
  ]
  gmodule_gir_dep = glib_subproject.get_variable('libgmodule')
340
341
endif

342
343
344
345
346
# NOTE: Always add this last so that we prefer the annotations in the sources
# (if they are available) since it contains 'backup' annotations that can be
# out of date.
gmodule_files += files('gmodule-2.0.c')

Patrick Griffis's avatar
Patrick Griffis committed
347
gir_files += custom_target('gir-gmodule',
348
  input: gmodule_files,
Patrick Griffis's avatar
Patrick Griffis committed
349
  output: 'GModule-2.0.gir',
350
  depends: [glib_gir, gir_giscanner_pymod, gmodule_gir_dep],
351
  depend_files: gir_giscanner_built_files,
Patrick Griffis's avatar
Patrick Griffis committed
352
353
  install: true,
  install_dir: girdir,
354
  command: gmodule_command + [
Patrick Griffis's avatar
Patrick Griffis committed
355
    '--include-uninstalled=' + glib_gir.full_path(),
356
    '--cflags-begin'] + glib_includes + extra_giscanner_cflags + [
Patrick Griffis's avatar
Patrick Griffis committed
357
358
359
360
361
    '--cflags-end',
    '@INPUT@',
  ]
)

362
## Gio
363
gio_files = []
Patrick Griffis's avatar
Patrick Griffis committed
364
365
366
367
368
369
370
371
372
gio_command = scanner_command + [
  '--identifier-prefix=G',
  '--symbol-prefix=g',
  '--c-include=gio/gio.h',
  '--namespace=Gio',
  '--nsversion=2.0',
  '--library=gio-2.0',
]

373
374
375
if dep_type == 'pkgconfig'
  gio_command += ['--external-library', '--pkg=gio-2.0']
  # Get the installed header list
376
  ret = run_command(python, '-c', globber.format(join_paths(glib_incdir, 'gio', '*.h')))
377
378
379
380
381
382
383
384
  if ret.returncode() != 0
    error('Failed to get gio header list')
  endif
  gio_headers = ret.stdout().strip().split('\n')
  # Get all gio (and gio-unix) sources. This is not entirely correct, but it's
  # probably fine since it matches what Autotools does. We are more exact in
  # the subproject case.
  if glib_srcdir != ''
385
    ret = run_command(python, '-c', globber.format(join_paths(glib_srcdir, 'gio', '*.c')))
386
387
388
389
390
    if ret.returncode() != 0
      error('Failed to get gio source list')
    endif
    gio_files += ret.stdout().strip().split('\n')
  endif
391
  gio_gir_dep = []
392
393
394
else
  gio_command += ['--pkg-export=gio-2.0']
  gio_headers = glib_subproject.get_variable('gio_headers')
395
396
397
398
399
  gio_files += [
    glib_subproject.get_variable('gio_sources'),
    glib_subproject.get_variable('gioenumtypes_h'),
    glib_subproject.get_variable('gnetworking_h'),
  ]
400
  gio_command += glib_libpaths
401
  gio_gir_dep = glib_subproject.get_variable('libgio')
Patrick Griffis's avatar
Patrick Griffis committed
402
403
endif

404
405
406
407
408
409
foreach h : gio_headers
  hstr = '@0@'.format(h)
  if not hstr.endswith('autocleanups.h')
    gio_files += h
  endif
endforeach
Patrick Griffis's avatar
Patrick Griffis committed
410

411
if giounix_dep.found()
412
  dep_type = giounix_dep.type_name()
413
414
  if dep_type == 'pkgconfig'
    gio_command += ['--pkg=gio-unix-2.0']
415
    giounix_includedir = get_option('gi_cross_pkgconfig_sysroot_path') + join_paths(giounix_dep.get_variable(pkgconfig: 'includedir'), 'gio-unix-2.0')
416
    # Get the installed gio-unix header list
417
    ret = run_command(python, '-c', globber.format(join_paths(giounix_includedir, 'gio', '*.h')))
418
419
420
421
422
423
424
    if ret.returncode() != 0
      error('Failed to get gio-unix header list')
    endif
    giounix_headers = ret.stdout().strip().split('\n')
  else
    gio_command += ['--pkg-export=gio-unix-2.0']
    giounix_headers = glib_subproject.get_variable('gio_unix_include_headers')
Patrick Griffis's avatar
Patrick Griffis committed
425
  endif
426
427
428
429
430
431
432
433
  # No filtering needed
  gio_files += giounix_headers
  # GIO Unix headers must be included explicitly since there is no catch-all
  # header that includes all of them unlike gio/gio.h above
  foreach header : giounix_headers
    hstr = '@0@'.format(header)
    hbase = hstr.split('/')[-1]
    gio_command += '--c-include=gio/@0@'.format(hbase)
Patrick Griffis's avatar
Patrick Griffis committed
434
435
436
  endforeach
endif

437
438
439
440
441
# NOTE: Always add this last so that we prefer the annotations in the sources
# (if they are available) since it contains 'backup' annotations that can be
# out of date.
gio_files += files('gio-2.0.c')

442
gio_gir = custom_target('gir-gio',
443
  input: gio_files,
Patrick Griffis's avatar
Patrick Griffis committed
444
  output: 'Gio-2.0.gir',
445
  depends: [gobject_gir, gir_giscanner_pymod, gio_gir_dep],
446
  depend_files: gir_giscanner_built_files,
Patrick Griffis's avatar
Patrick Griffis committed
447
448
  install: true,
  install_dir: girdir,
449
450
  command: gio_command + [
    '--include-uninstalled=' + gobject_gir.full_path(),
451
    '--cflags-begin'] + glib_includes + extra_giscanner_cflags + [
452
453
454
455
456
    '-DGIO_COMPILATION',
    '-DG_SETTINGS_ENABLE_BACKEND',
    '--cflags-end',
    '@INPUT@',
  ]
Patrick Griffis's avatar
Patrick Griffis committed
457
458
)

459
460
gir_files += gio_gir

Patrick Griffis's avatar
Patrick Griffis committed
461
# GIRepository
462
463
464
465

girepository_command = scanner_command + [
  '--identifier-prefix=GI',
  '--symbol-prefix=g',
466
  '--symbol-prefix=gi',
467
468
469
470
  '--c-include=girepository.h',
  '--namespace=GIRepository',
  '--nsversion=2.0',
  '--library=girepository-1.0',
471
472
  '--pkg-export=gobject-introspection-1.0',
  '-L' + meson.current_build_dir() + '/../girepository',
473
474
]

475
if dep_type != 'pkgconfig'
476
477
478
  girepository_command += glib_libpaths
endif

Patrick Griffis's avatar
Patrick Griffis committed
479
480
481
gir_files += custom_target('gir-girepository',
  input: girepo_gir_sources,
  output: 'GIRepository-2.0.gir',
482
483
  depends: [gobject_gir, gir_giscanner_pymod, girepo_lib],
  depend_files: gir_giscanner_built_files,
Patrick Griffis's avatar
Patrick Griffis committed
484
485
  install: true,
  install_dir: girdir,
486
  command: girepository_command + [
Patrick Griffis's avatar
Patrick Griffis committed
487
    '--include-uninstalled=' + gobject_gir.full_path(),
488
    '--cflags-begin'] + glib_includes + extra_giscanner_cflags + [
489
    '-I' + meson.current_source_dir() + '/../girepository',
490
    '-I' + meson.current_build_dir() + '/../girepository',
491
    '-DGI_COMPILATION',
Patrick Griffis's avatar
Patrick Griffis committed
492
493
494
495
496
    '--cflags-end',
    '@INPUT@',
  ]
)

Tomasz Mi膮sko's avatar
Tomasz Mi膮sko committed
497
typelibs = []
498
499
if get_option('gi_cross_binary_wrapper') != ''
    gircompiler_command = [get_option('gi_cross_binary_wrapper'), gircompiler.full_path(), ]
500
else
501
502
503
504
    gircompiler_command = [gircompiler, ]
endif

gircompiler_command += [ '-o', '@OUTPUT@', '@INPUT@',
505
506
              '--includedir', meson.current_build_dir(),
              '--includedir', meson.current_source_dir(),
507
]
508

Patrick Griffis's avatar
Patrick Griffis committed
509
foreach gir : gir_files
Tomasz Mi膮sko's avatar
Tomasz Mi膮sko committed
510
  typelibs += custom_target('generate-typelib-@0@'.format(gir).underscorify(),
Patrick Griffis's avatar
Patrick Griffis committed
511
512
    input: gir,
    output: '@BASENAME@.typelib',
513
    depends: [gobject_gir, gircompiler, ],
514
    command: gircompiler_command,
Patrick Griffis's avatar
Patrick Griffis committed
515
516
517
518
    install: true,
    install_dir: typelibdir,
  )
endforeach