1project(
2  'polkit', ['c', 'cpp'],
3  version: '0.120',
4  license: 'LGPL2+',
5  default_options: [
6    'buildtype=debugoptimized',
7    'prefix=/usr',
8    'cpp_std=c++17',
9  ],
10  meson_version: '>= 0.50.0',
11)
12
13pk_version = meson.project_version()
14
15pk_api_version = '1'
16pk_api_name = '@0@-@1@'.format(meson.project_name(), pk_api_version)
17
18pk_gir_ns = 'Polkit'
19pk_gir_version = '1.0'
20
21pk_prefix = get_option('prefix')
22pk_datadir = get_option('datadir')
23pk_includedir = get_option('includedir')
24pk_libdir = get_option('libdir')
25pk_mandir = get_option('mandir')
26pk_sysconfdir = get_option('sysconfdir')
27
28pk_pkgdatadir = pk_datadir / pk_api_name
29pk_pkgincludedir = pk_includedir / pk_api_name
30# note that this is always 'lib', not lib64 or lib/x86_64-linux-gnu
31pk_libprivdir = 'lib' / pk_api_name
32pk_pkgsysconfdir = pk_sysconfdir / pk_api_name
33
34pk_actiondir = pk_api_name / 'actions'
35pk_pkgactiondir = pk_datadir / pk_actiondir
36
37soversion = 0
38current = 0
39revision = 0
40libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
41
42gnome = import('gnome')
43i18n = import('i18n')
44pkg = import('pkgconfig')
45
46source_root = meson.current_source_dir()
47build_root = meson.current_build_dir()
48
49data_dir = source_root / 'data'
50its_dir = source_root / 'gettext'
51po_dir = source_root / 'po'
52
53its_data = files(
54  'gettext/its/polkit.its',
55  'gettext/its/polkit.loc',
56)
57
58install_data(
59  its_data,
60  install_dir: pk_datadir / 'gettext/its',
61)
62
63top_inc = include_directories('.')
64
65cc = meson.get_compiler('c')
66
67config_h = configuration_data()
68
69# defines
70set_defines = [
71  # package
72  ['PACKAGE_BUGREPORT', 'http://lists.freedesktop.org/mailman/listinfo/polkit-devel'],
73  ['PACKAGE_NAME', meson.project_name()],
74  ['PACKAGE_URL', 'http://www.freedesktop.org/wiki/Software/polkit'],
75  ['PACKAGE_VERSION', pk_version],
76  ['VERSION', pk_version],
77  # i18n
78  ['GETTEXT_PACKAGE', pk_api_name],
79]
80
81foreach define: set_defines
82  config_h.set_quoted(define[0], define[1])
83endforeach
84
85# Globally define_GNU_SOURCE and therefore enable the GNU extensions
86config_h.set('_GNU_SOURCE', true)
87
88# functions
89check_functions = [
90  'clearenv',
91  'fdatasync',
92]
93
94foreach func: check_functions
95  config_h.set('HAVE_' + func.to_upper(), cc.has_function(func))
96endforeach
97
98# compiler flags
99common_c_flags = [
100  # FIXME: this should go as 'c_std=c99' in project's default_options.
101  #        https://github.com/mesonbuild/meson/issues/1889
102  #        https://github.com/mesonbuild/meson/pull/6729
103  '-std=c99',
104  '-DHAVE_CONFIG_H',
105]
106compiler_flags = []
107compiler_c_flags = []
108
109if get_option('buildtype').contains('debug')
110  compiler_c_flags += cc.get_supported_arguments([
111    '-Waggregate-return',
112    '-Wdeclaration-after-statement',
113    '-Wformat=2',
114    '-Wimplicit-function-declaration',
115    '-Winit-self',
116    '-Wmissing-declarations',
117    '-Wmissing-include-dirs',
118    '-Wmissing-prototypes',
119    '-Wstrict-prototypes',
120  ])
121endif
122
123add_project_arguments(common_c_flags + compiler_c_flags, language: 'c')
124
125glib_req_version = '>= 2.30.0'
126
127gio_dep = dependency('gio-2.0', version: glib_req_version)
128gio_unix_dep = dependency('gio-unix-2.0', version: glib_req_version)
129glib_dep = dependency('glib-2.0', version: glib_req_version)
130gobject_dep = dependency('gobject-2.0', version: glib_req_version)
131
132expat_dep = dependency('expat')
133assert(cc.has_header('expat.h', dependencies: expat_dep), 'Can\'t find expat.h. Please install expat.')
134assert(cc.has_function('XML_ParserCreate', dependencies: expat_dep), 'Can\'t find expat library. Please install expat.')
135
136mozjs_dep = dependency('mozjs-78')
137
138dbus_dep = dependency('dbus-1', required: false)
139dbus_policydir = pk_prefix / pk_sysconfdir / 'dbus-1/system.d'
140if dbus_dep.found()
141  dbus_system_bus_services_dir = dbus_dep.get_pkgconfig_variable('system_bus_services_dir', define_variable: ['datadir', pk_prefix / pk_datadir])
142else
143  # libdbus development files not installed, assume a standard layout
144  dbus_system_bus_services_dir = pk_prefix / pk_datadir / 'dbus-1' / 'system-services'
145endif
146
147# check OS
148host_system = host_machine.system()
149config_h.set('HAVE_' + host_system.to_upper(), true)
150
151# Check whether setnetgrent has a return value
152config_h.set('HAVE_NETGROUP_H', cc.has_header('netgroup.h'))
153
154setnetgrent_return_src = '''
155  #include <stddef.h>
156  #ifdef HAVE_NETGROUP_H
157  #include <netgroup.h>
158  #else
159  #include <netdb.h>
160  #endif
161  int main() {
162      int r = setnetgrent (NULL);
163  };
164'''
165
166config_h.set('HAVE_SETNETGRENT_RETURN', cc.compiles(setnetgrent_return_src, name: 'setnetgrent return support'))
167
168# Select wether to use libsystemd-login, libelogind or ConsoleKit for session tracking
169session_tracking = get_option('session_tracking')
170enable_logind = (session_tracking != 'ConsoleKit')
171if enable_logind
172  if session_tracking == 'libsystemd-login'
173    logind_dep = dependency('libsystemd', required: false)
174    if not logind_dep.found()
175      logind_dep = dependency('libsystemd-login', not_found_message: 'libsystemd support requested but libsystemd or libsystemd-login library not found')
176    endif
177  else
178    logind_dep = dependency('libelogind', not_found_message: 'libelogind support requested but libelogind library not found')
179  endif
180
181  func = 'sd_uid_get_display'
182  config_h.set10('HAVE_' + func.to_upper(), cc.has_function(func, dependencies: logind_dep))
183
184  # systemd unit / service files
185  systemd_systemdsystemunitdir = get_option('systemdsystemunitdir')
186  if systemd_systemdsystemunitdir == ''
187    systemd_dep = dependency('systemd', not_found_message: 'systemd required but not found, please provide a valid systemd user unit dir or disable it')
188    # FIXME: systemd.pc file does not use variables with relative paths, so `define_variable` cannot be used
189    systemd_systemdsystemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
190  endif
191endif
192config_h.set('HAVE_LIBSYSTEMD', enable_logind)
193
194# User for running polkitd
195polkitd_user = get_option('polkitd_user')
196config_h.set_quoted('POLKITD_USER', polkitd_user)
197
198# Select which authentication framework to use
199auth_deps = []
200
201auth_fw = get_option('authfw')
202enable_pam = (auth_fw == 'pam')
203if enable_pam
204  # Check for PAM
205  pam_dep = cc.find_library('pam')
206  assert(pam_dep.found() and cc.has_function('pam_start', dependencies: pam_dep), 'Could not find pam/pam-devel, please install the needed packages.')
207
208  # how to call pam_strerror
209  pam_strerror_src = '''
210    #include <stdio.h>
211    #include <stdlib.h>
212    #include <security/pam_appl.h>
213    #endif
214    int main() {
215      @0@
216    };
217  '''
218
219  # FIXME: Not necessary anymore?
220  if cc.compiles(pam_strerror_src.format('pam_handle_t *pamh = 0; char *s = pam_strerror(pamh, PAM_SUCCESS);'))
221    # FIXME: unused?
222    config_h.set('PAM_STRERROR_TWO_ARGS', true)
223  else
224    message('how to call pam_strerror: ' + cc.compiles(pam_strerror_src.format('char *s = pam_strerror(PAM_SUCCESS);')).to_string('1', 'unknown'))
225  endif
226
227  pam_prefix = get_option('pam_prefix')
228  if pam_prefix == ''
229    pam_prefix = pk_sysconfdir
230  else
231    message('PAM files will be installed in prefix ' + pam_prefix)
232  endif
233
234  pam_module_dir = get_option('pam_module_dir')
235  if pam_module_dir == ''
236    pam_module_dir = pk_libdir / 'security'
237  endif
238
239  auth_deps += pam_dep
240elif auth_fw == 'shadow'
241  auth_deps += cc.find_library('crypt')
242endif
243config_h.set('POLKIT_AUTHFW_' + auth_fw.to_upper(), true)
244
245# FIXME: sigtimedwait is not used anywhere?
246'''
247if host_system == 'solaris'
248  rt_dep = cc.find_library('rt')
249  cc.has_function('sigtimedwait', dependencies: rt_dep)
250else
251  cc.has_function('sigtimedwait')
252endif
253'''
254
255os_type = get_option('os_type')
256if os_type == ''
257  os_paths = [
258    ['redhat', '/etc/sysconfig/network-scripts'],
259    ['suse', '/etc/SuSE-release'],
260    ['debian', '/etc/debian_version'],
261    ['gentoo', '/etc/gentoo-release'],
262    ['pardus', '/etc/pardus-release'],
263  ]
264
265  foreach os_path: os_paths
266    if run_command('test', '-e', os_path[1]).returncode() == 0
267      os_type = os_path[0]
268      break
269    endif
270  endforeach
271
272  if os_type == ''
273    message('Linux distribution autodetection failed, specify the distribution to target using -Dos_type=')
274  endif
275endif
276
277pam_include = get_option('pam_include')
278if pam_include == ''
279  if ['suse', 'solaris'].contains(os_type)
280    pam_conf = {
281      'PAM_FILE_INCLUDE_AUTH': 'common-auth',
282      'PAM_FILE_INCLUDE_ACCOUNT': 'common-account',
283      'PAM_FILE_INCLUDE_PASSWORD': 'common-password',
284      'PAM_FILE_INCLUDE_SESSION': 'common-session',
285    }
286  elif os_type.contains('bsd')
287    pam_conf = {
288      'PAM_FILE_INCLUDE_AUTH': 'system',
289      'PAM_FILE_INCLUDE_ACCOUNT': 'system',
290      'PAM_FILE_INCLUDE_PASSWORD': 'system',
291      'PAM_FILE_INCLUDE_SESSION': 'system',
292    }
293  #if ['redhat', 'gentoo', 'pardus'].contains(os_type)
294  else
295    pam_conf = {
296      'PAM_FILE_INCLUDE_AUTH': 'system-auth',
297      'PAM_FILE_INCLUDE_ACCOUNT': 'system-auth',
298      'PAM_FILE_INCLUDE_PASSWORD': 'system-auth',
299      'PAM_FILE_INCLUDE_SESSION': 'system-auth',
300    }
301  endif
302else
303  pam_conf = {
304    'PAM_FILE_INCLUDE_AUTH': pam_include,
305    'PAM_FILE_INCLUDE_ACCOUNT': pam_include,
306    'PAM_FILE_INCLUDE_PASSWORD': pam_include,
307    'PAM_FILE_INCLUDE_SESSION': pam_include,
308  }
309endif
310
311enable_introspection = get_option('introspection')
312if enable_introspection
313  dependency('gobject-introspection-1.0', version: '>= 0.6.2')
314endif
315
316content_files = files('COPYING')
317
318subdir('actions')
319subdir('data')
320subdir('src')
321subdir('docs')
322subdir('po')
323
324enable_tests = get_option('tests')
325if enable_tests
326  subdir('test')
327endif
328
329configure_file(
330  output: 'config.h',
331  configuration: config_h,
332)
333
334output = '\n        ' + meson.project_name() + ' ' + meson.project_version() + '\n'
335output += '        ============\n\n'
336output += '        prefix:                   ' + pk_prefix + '\n'
337output += '        datadir:                  ' + pk_datadir + '\n\n'
338output += '        includedir:               ' + pk_includedir + '\n'
339output += '        libdir:                   ' + pk_libdir + '\n'
340output += '        sysconfdir:               ' + pk_sysconfdir + '\n'
341output += '        source code location:     ' + source_root + '\n'
342output += '        compiler:                 ' + cc.get_id() + '\n'
343output += '        c_flags:                  ' + ' '.join(compiler_c_flags) + '\n\n'
344if enable_man
345  output += '        xsltproc:                 ' + xsltproc.path() + '\n'
346endif
347output += '        introspection:            ' + enable_introspection.to_string() + '\n'
348output += '        Distribution/OS:          ' + os_type + '\n'
349output += '        Authentication framework: ' + auth_fw + '\n'
350output += '        Session tracking:         ' + session_tracking + '\n'
351if enable_logind
352  output += '        systemdsystemunitdir:     ' + systemd_systemdsystemunitdir + '\n'
353endif
354output += '        polkitd user:             ' + polkitd_user + ' \n'
355output += '        PAM support:              ' + enable_pam.to_string() + '\n\n'
356if enable_pam
357  output += '        PAM file auth:            ' + pam_conf['PAM_FILE_INCLUDE_AUTH'] + '\n'
358  output += '        PAM file acount:          ' + pam_conf['PAM_FILE_INCLUDE_ACCOUNT'] + '\n'
359  output += '        PAM file password:        ' + pam_conf['PAM_FILE_INCLUDE_PASSWORD'] + '\n'
360  output += '        PAM file session:         ' + pam_conf['PAM_FILE_INCLUDE_SESSION'] + '\n\n'
361endif
362output += '        Building api docs:        ' + enable_gtk_doc.to_string() + '\n'
363output += '        Building man pages:       ' + enable_man.to_string() + '\n'
364output += '        Building examples:        ' + enable_examples.to_string() + '\n'
365output += '        Building tests:           ' + enable_tests.to_string()
366message(output)
367