meson.build 16.8 KB
Newer Older
1
project(
2
  'network-manager-applet', 'c',
3
  version: '1.8.21',
4 5 6
  license: 'GPL2+',
  default_options: [
    'buildtype=debugoptimized',
7
    'c_std=gnu99'
8
  ],
9
  meson_version: '>= 0.43.0'
10 11
)

12
nma_name = 'nm-applet'
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

nma_version = meson.project_version()
version_array = nma_version.split('.')
nma_major_version = version_array[0].to_int()
nma_minor_version = version_array[1].to_int()
nma_micro_version = version_array[2].to_int()

nma_gir_version = '1.0'
nma_gir_prefix = 'NMA'

nma_gir_ns = 'NMA'
nma_gtk_gir_ns = 'NMGtk'

nma_prefix = get_option('prefix')
nma_bindir = join_paths(nma_prefix, get_option('bindir'))
nma_datadir = join_paths(nma_prefix, get_option('datadir'))
nma_includedir = join_paths(nma_prefix, get_option('includedir'))
nma_libdir = join_paths(nma_prefix, get_option('libdir'))
nma_libexecdir = join_paths(nma_prefix, get_option('libexecdir'))
nma_localedir = join_paths(nma_prefix, get_option('localedir'))
nma_mandir = join_paths(nma_prefix, get_option('mandir'))
nma_sysconfdir = join_paths(nma_prefix, get_option('sysconfdir'))

nma_appdir = join_paths(nma_datadir, 'applications')
nma_autostartdir = join_paths(nma_sysconfdir, 'xdg', 'autostart')
nma_icondir = join_paths(nma_datadir, 'icons')

soversion = 0
current = 0
revision = 0
libversion = '@0@.@1@.@2@'.format(soversion, current, revision)

nma_debug = get_option('buildtype').contains('debug')

cc = meson.get_compiler('c')

config_h = configuration_data()

# defines
52 53
config_h.set_quoted('GETTEXT_PACKAGE', nma_name)
config_h.set_quoted('VERSION', nma_version)
54 55

# types
56 57 58
if not cc.has_type('pid_t', prefix: '#include<sys/types.h>')
  config_h.set('pid_t', 'int')
endif
59 60

# compiler flags
61
common_flags = []
62 63
common_ldflags = []

64
enable_ld_gc = get_option('ld_gc')
65 66 67 68 69 70 71 72 73
if enable_ld_gc
  test_cflags = [
    '-fdata-sections',
    '-ffunction-sections',
  ]

  test_ldflags = ['-Wl,--gc-sections']

  foreach cflag: test_cflags + test_ldflags
74
    assert(cc.has_argument(cflag), 'Unused symbol eviction requested but not supported. Use -Dld_gc=false to build without it.')
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  endforeach

  common_flags += test_cflags
  common_ldflags += test_ldflags
endif

if nma_debug
  test_cflags = [
    '-Wdeclaration-after-statement',
    '-Wfloat-equal',
    '-Wformat=2',
    '-Wimplicit-fallthrough',
    '-Winit-self',
    '-Wmissing-declarations',
    '-Wmissing-include-dirs',
    '-Wmissing-prototypes',
    '-Wno-duplicate-decl-specifier',
    '-Wno-format-truncation',
    '-Wno-format-y2k',
    '-Wno-missing-field-initializers',
    '-Wno-pragmas',
    '-Wno-sign-compare',
    '-Wno-unused-parameter',
    '-Wshadow',
    '-Wstrict-prototypes',
100 101
    '-Wundef',
    '-Wvla',
102 103
  ]

104
  common_flags += cc.get_supported_arguments(test_cflags)
105 106 107 108 109 110 111 112 113 114 115
endif

add_project_arguments(common_flags, language: 'c')
add_project_link_arguments(common_ldflags, language: 'c')

ldflag = '-Wl,--version-script'
have_version_script = host_machine.system().contains('linux') and cc.has_argument(ldflag)

linker_script_ver = join_paths(meson.source_root(), 'linker-script-binary.ver')

# Check for iso-codes for country names translation
116
enable_iso_codes = get_option('iso_codes')
117 118 119 120 121
message('whether to disable iso-codes at build-time: ' + enable_iso_codes.to_string())
if enable_iso_codes
  iso_codes_dep = dependency('iso-codes')

  str = 'Consider installing the package or adjusting the PKG_CONFIG_PATH environment variable.\n'
122
  str += 'You can also disable build-time check for \'iso-codes\' via -Diso_codes=false'
123 124 125 126 127 128 129 130 131 132
  assert(iso_codes_dep.found(), str)

  iso_3166 = iso_codes_dep.get_pkgconfig_variable('domains').contains('iso_3166')
  message('whether iso-codes has iso_3166 domain: ' + iso_3166.to_string())

  config_h.set_quoted('ISO_CODES_PREFIX', iso_codes_dep.get_pkgconfig_variable('prefix'))
else
  config_h.set_quoted('ISO_CODES_PREFIX', nma_prefix)
endif

133 134 135 136 137 138 139
# Check for mobile-broadband-provider-info for Mobile Broadband wizard
enable_mobile_broadband_provider_info = get_option('mobile_broadband_provider_info')
message('whether to enable mobile-broadband-provider-info at build-time: ' + enable_mobile_broadband_provider_info.to_string())
if enable_mobile_broadband_provider_info
  mobile_broadband_provider_info_dep = dependency('mobile-broadband-provider-info')
  config_h.set_quoted('MOBILE_BROADBAND_PROVIDER_INFO_DATABASE', mobile_broadband_provider_info_dep.get_pkgconfig_variable('database'))
else
140
  config_h.set_quoted('MOBILE_BROADBAND_PROVIDER_INFO_DATABASE', join_paths(nma_datadir, 'mobile-broadband-provider-info', 'serviceproviders.xml'))
141 142
endif

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
gio_dep = dependency('gio-2.0', version: '>= 2.38')
gmodule_export_dep = dependency('gmodule-export-2.0')
libsecret_dep = dependency('libsecret-1', version: '>= 0.18')

m_dep = cc.find_library('m')

# Check for gtk+
gtk_req_version = '>= 3.4'

gtk_dep = declare_dependency(
  dependencies: dependency('gtk+-3.0', version: gtk_req_version),
  compile_args: [
    '-DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_4',
    '-DGTK_VERSION_MAX_ALLOWED=GTK_VERSION_3_4'
  ]
)

# Check for gudev
gudev_dep = dependency('gudev-1.0', version: '>= 147')

# Check for libnotify >= 0.7
libnotify_dep = dependency('libnotify', version: '>= 0.4.3')
config_h.set10('HAVE_LIBNOTIFY_07', libnotify_dep.found() and libnotify_dep.version().version_compare('>= 0.7'),
               description: 'Define if you have libnotify 0.7 or later')

# API documentation
nm_req_version = '>= 1.7'

deps = [
  gio_dep,
  gmodule_export_dep,
  dependency('libnm', version: nm_req_version)
]

cflags = [
  '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38',
  '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_38',
  '-DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_8',
  '-DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_8'
]

libnm_dep = declare_dependency(
  dependencies: deps,
  compile_args: cflags
)

189
enable_libnm_gtk = get_option('libnm_gtk')
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
if enable_libnm_gtk
  deps = [
    gio_dep,
    gmodule_export_dep,
    dependency('libnm-glib', version: nm_req_version),
    dependency('libnm-glib-vpn', version: nm_req_version),
    dependency('libnm-util', version: nm_req_version),
    dependency('NetworkManager', version: nm_req_version)
  ]

  cflags = [
    '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38',
    '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_38',
    '-DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_4',
    '-DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_4'
  ]

  libnm_glib_dep = declare_dependency(
    dependencies: deps,
    compile_args: cflags
  )
endif

213
enable_appindicator = get_option('appindicator')
214
if enable_appindicator == 'auto' or enable_appindicator == 'yes'
215 216 217 218
  appindicator_dep = dependency('ayatana-appindicator3-0.1', required: false)
  if appindicator_dep.found()
    enable_appindicator = 'ayatana'
  else
219
    appindicator_dep = dependency('appindicator3-0.1', required: false)
220 221
    if appindicator_dep.found()
      enable_appindicator = 'ubuntu'
222 223
    else
      assert(appindicator_dep.found(), 'Neither Ubuntu\'s AppIndicator nor Ayatana AppIndicator found.')
224 225
    endif
  endif
226 227 228 229
elif enable_appindicator == 'ayatana'
  appindicator_dep = dependency('ayatana-appindicator3-0.1')
elif enable_appindicator == 'ubuntu'
  appindicator_dep = dependency('appindicator3-0.1')
230 231
endif

232 233 234 235
if enable_appindicator == 'no'
  config_h.set('WITH_APPINDICATOR', false)
  config_h.set('USE_AYATANA_INDICATORS', false)
elif enable_appindicator == 'ubuntu'
236
  dbusmenu_dep = dependency('dbusmenu-gtk3-0.4', version: '>= 16.04.0')
237 238
  config_h.set10('WITH_APPINDICATOR', true)
  config_h.set10('USE_AYATANA_INDICATORS', false)
239 240
elif enable_appindicator == 'ayatana'
  dbusmenu_dep = dependency('dbusmenu-gtk3-0.4', version: '>= 16.04.0')
241 242
  config_h.set10('WITH_APPINDICATOR', true)
  config_h.set10('USE_AYATANA_INDICATORS', true)
243
else
244
  error('Options allowed for -Dappindicator=<str> are: no, yes|auto, ayatana, ubuntu.')
245 246 247
endif

# ModemManager1 with libmm-glib for WWAN support
248
enable_wwan = get_option('wwan')
249 250
if enable_wwan
  mm_glib_dep = dependency('mm-glib', required: false)
251
  assert(mm_glib_dep.found(), 'libmm-glib is needed for WWAN support. Use -Dwwan=false to build without it.')
252 253 254 255
endif
config_h.set10('WITH_WWAN', enable_wwan)

# SELinux
256
enable_selinux = get_option('selinux')
257 258
if enable_selinux
  libselinux_dep = dependency('libselinux', required: false)
259
  assert(libselinux_dep.found(), 'libselinux is needed for SELinux label support in configuration editor. Use -Dselinux=false to build without it.')
260 261 262 263
endif
config_h.set10('WITH_SELINUX', enable_selinux)

# Jansson for team configuration editing
264
enable_team = get_option('team')
265 266
if enable_team
  jansson_dep = dependency('jansson', version: '>= 2.7', required: false)
267
  assert(jansson_dep.found(), 'jansson is needed for team configuration editor. Use -Dteam=false to build without it.')
268 269 270 271
endif
config_h.set10('WITH_JANSSON', enable_team)

# GCR for PKCS#11 enabled certificate chooser
272
enable_gcr = get_option('gcr')
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
if enable_gcr
  deps = [
    dependency('gcr-3', version: '>= 3.14'),
    dependency('gck-1', version: '>= 3.14')
  ]

  cflags = [
    '-DGCR_API_SUBJECT_TO_CHANGE',
    '-DGCK_API_SUBJECT_TO_CHANGE'
  ]

  # GCR API is declared subject to change, do an extensive check of the prototypes
  gcr_src = '''
    #ifndef GCR_API_SUBJECT_TO_CHANGE
    # define GCR_API_SUBJECT_TO_CHANGE
    #endif
    #ifndef GCK_API_SUBJECT_TO_CHANGE
    # define GCK_API_SUBJECT_TO_CHANGE
    #endif

    #include <gcr/gcr.h>
    #include <gck/gck.h>

    const GckAttribute *gck_attributes_find (GckAttributes *attrs, gulong attr_type);
    gboolean gck_attributes_find_string (GckAttributes *attrs, gulong attr_type, gchar **value);
    gboolean gck_attributes_find_ulong (GckAttributes *attrs, gulong attr_type, gulong *value);
    GckAttributes *gck_attributes_new_empty (gulong first_type, ...);
    void gck_attributes_unref (gpointer attrs);
    void gck_builder_add_all (GckBuilder *builder, GckAttributes *attrs);
    void gck_builder_add_only (GckBuilder *builder, GckAttributes *attrs, gulong only_type, ...);
    GckAttributes *gck_builder_end (GckBuilder *builder);
    GckBuilder *gck_builder_new (GckBuilderFlags flags);
    void gck_enumerator_next_async (GckEnumerator *self, gint max_objects, GCancellable *cancellable,
                                    GAsyncReadyCallback callback, gpointer user_data);
    GList *gck_enumerator_next_finish (GckEnumerator *self, GAsyncResult *result, GError **error);
    void gck_list_unref_free (GList *reflist);
    GList *gck_modules_get_slots (GList *modules, gboolean token_present);
    void gck_modules_initialize_registered_async (GCancellable *cancellable, GAsyncReadyCallback callback,
                                                  gpointer user_data);
    GList *gck_modules_initialize_registered_finish (GAsyncResult *result, GError **error);
    void gck_object_get_async (GckObject *self, const gulong *attr_types, guint n_attr_types,
                               GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
    GckAttributes *gck_object_get_finish (GckObject *self, GAsyncResult *result, GError **error);
    void gck_session_login_async (GckSession *self, gulong user_type, const guchar *pin,
                                  gsize n_pin, GCancellable *cancellable,
                                  GAsyncReadyCallback callback, gpointer user_data);
    gboolean gck_session_login_finish (GckSession *self, GAsyncResult *result, GError **error);
    GckSlotInfo *gck_slot_get_info (GckSlot *self);
    GckTokenInfo *gck_slot_get_token_info (GckSlot *self);
    void gck_slot_open_session_async (GckSlot *self, GckSessionOptions options, GCancellable *cancellable,
                                      GAsyncReadyCallback callback, gpointer user_data);
    GckSession *gck_slot_open_session_finish (GckSlot *self, GAsyncResult *result, GError **error);
    void gck_token_info_free (GckTokenInfo *token_info);
    gchar *gck_uri_build (GckUriData *uri_data, GckUriFlags flags);
    void gck_uri_data_free (GckUriData *uri_data);
    GckUriData *gck_uri_parse (const gchar *string, GckUriFlags flags, GError **error);
    gchar *gcr_certificate_get_issuer_name (GcrCertificate *self);
    gchar *gcr_certificate_get_subject_name (GcrCertificate *self);
    GcrCertificate *gcr_simple_certificate_new (const guchar *data, gsize n_data);
  '''

334
  assert(cc.compiles(gcr_src, dependencies: deps), 'gcr support was requested, but the gcr library is not available. Use -Dgcr=false to build without it.')
335 336 337 338 339 340 341 342 343

  gcr_dep = declare_dependency(
    dependencies: deps,
    compile_args: cflags
  )
endif
config_h.set10('WITH_GCR', enable_gcr)

# introspection support
344
enable_introspection = get_option('introspection')
345 346
if enable_introspection
  gir_dep = dependency('gobject-introspection-1.0', version: '>= 0.9.6', required: false)
347
  assert(gir_dep.found(), 'introspection support was requested, but the gobject-introspection library is not available. Use -Dintrospection=false to build without it.')
348 349
endif

350
more_asserts = get_option('more_asserts')
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
if more_asserts == 'no'
  more_asserts = 0
elif more_asserts == 'yes'
  more_asserts = 100
else
  more_asserts = more_asserts.to_int()
endif
config_h.set('NM_MORE_ASSERTS', more_asserts)

gnome = import('gnome')
i18n = import('i18n')
pkg = import('pkgconfig')

po_dir = join_paths(meson.source_root(), 'po')

intltool_merge = find_program('intltool-merge')
intltool_cache = join_paths(po_dir, '.intltool-merge-cache')
intltool_desktop_cmd = [intltool_merge, '-d', '-u', '-c', intltool_cache, po_dir, '@INPUT@', '@OUTPUT@']
intltool_xml_cmd = [intltool_merge, '-x', '-u', '-c', intltool_cache, po_dir, '@INPUT@', '@OUTPUT@']

top_inc = include_directories('.')

subdir('po')
subdir('icons')
subdir('shared')
subdir('src')
subdir('man')

desktop = 'nm-applet.desktop'

# FIXME: The same target can not be copied into two directories.
#        There is a workaround in meson_post_install.py until proper solution arises:
#        https://groups.google.com/forum/#!topic/mesonbuild/3iIoYPrN4P0
custom_target(
  desktop,
  input: desktop + '.in',
  output: desktop,
  command: intltool_desktop_cmd,
  install: true,
  install_dir: nma_appdir
  #install_dir: [
  #  nma_appdir,
  #  nma_autostartdir
  #]
)

desktop = 'nm-connection-editor.desktop'

custom_target(
  desktop,
  input: desktop + '.in',
  output: desktop,
  command: intltool_desktop_cmd,
  install: true,
  install_dir: nma_appdir
)

408
appdata = 'nm-connection-editor.appdata.xml'
409 410

custom_target(
411 412 413
  appdata,
  input: appdata + '.in',
  output: appdata,
414 415
  command: intltool_xml_cmd,
  install: true,
416
  install_dir: join_paths(nma_datadir, 'metainfo')
417 418 419
)

schema_conf = configuration_data()
420
schema_conf.set('GETTEXT_PACKAGE', nma_name)
421

422
schema = 'org.gnome.nm-applet.gschema.xml'
423 424 425 426 427 428 429 430 431 432

configure_file(
  input: schema + '.in',
  output: schema,
  install: true,
  install_dir: join_paths(nma_datadir, 'glib-2.0', 'schemas'),
  configuration: schema_conf
)

install_data(
433
  'nm-applet.convert',
434 435 436 437
  install_dir: join_paths(nma_datadir, 'GConf', 'gsettings')
)

# documentation
438
enable_gtk_doc = get_option('gtk_doc')
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
if enable_gtk_doc
  mod_name = 'libnma'

  private_headers = [
    'nma-cert-chooser-button.h',
    'nma-cert-chooser-private.h',
    'nma-pkcs11-cert-chooser-dialog.h',
    'nma-pkcs11-token-login-dialog.h',
    'nma-resources.h',
    'nma-version.h'
  ]

  private_sources = [
    'nma-cert-chooser-button.c',
    'nma-file-cert-chooser.c',
    'nma-pkcs11-cert-chooser-dialog.c',
    'nma-pkcs11-cert-chooser.c',
    'nma-pkcs11-token-login-dialog.c',
    'nma-resources.c'
  ]

460 461
  ent_conf = configuration_data()
  ent_conf.set_quoted('PACKAGE', meson.project_name())
462
  ent_conf.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/network-manager-applet/issues')
463 464 465 466 467 468
  ent_conf.set_quoted('PACKAGE_NAME', nma_name)
  ent_conf.set_quoted('PACKAGE_STRING', '@0@ @1@'.format(nma_name, nma_version))
  ent_conf.set_quoted('PACKAGE_TARNAME', meson.project_name())
  ent_conf.set_quoted('PACKAGE_URL', '')
  ent_conf.set_quoted('PACKAGE_VERSION', nma_version)

469 470 471 472 473
  ent = 'gtkdocentities.ent'

  configure_file(
    input: ent + '.in',
    output: ent,
474
    configuration: ent_conf
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
  )

  doc_path = join_paths(nma_datadir, 'gtk-doc', 'html', mod_name)

  gnome.gtkdoc(
    mod_name,
    main_xml: mod_name + '-docs.xml',
    src_dir: libnma_inc,
    dependencies: libnma_dep,
    scan_args: [
      '--rebuild-types',
      '--rebuild-sections',
      '--ignore-headers=' + ' '.join(private_headers)
    ],
    mkdb_args: '--ignore-files=' + ' '.join(private_headers + private_sources),
    gobject_typesfile: mod_name + '.types',
    install: true,
    install_dir: doc_path
  )
endif

496 497 498 499 500 501 502 503
config = 'config.h'

configure_file(
  input: config + '.meson',
  output: config,
  configuration: config_h
)

504 505 506 507 508 509 510 511 512
meson.add_install_script(
  'meson_post_install.py',
  nma_datadir,
  nma_sysconfdir
)

output = '\n  Build legacy library libnm-gtk: ' + enable_libnm_gtk.to_string() + '\n'
output += '  GCR: ' + enable_gcr.to_string() + '\n'
output += '  LTO: ' + get_option('b_lto').to_string() + '\n'
513 514
output += '  Linker garbage collection: ' + enable_ld_gc.to_string() + '\n'
output += '  libappindicator: ' + enable_appindicator
515
message(output)