• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1project('libsoup', 'c',
2        version: '2.71.0',
3        meson_version : '>=0.50',
4        license : 'LGPL2',
5        default_options : 'c_std=c89')
6
7gnome = import('gnome')
8
9soup_version = meson.project_version()
10version_arr = soup_version.split('.')
11soup_version_major = version_arr[0]
12soup_version_minor = version_arr[1]
13soup_version_micro = version_arr[2]
14
15# Before making a release, the libversion string should be modified.
16#
17#  * Bump the first component if binary compatibility has been broken; or
18#  * Bump the second component if new APIs are added; or
19#  * Bump the third component otherwise.
20#
21# When bumping the first component version, set the second and third components
22# to 0. When bumping the second version, set the third one to zero.
23libversion = '1.10.0'
24apiversion = '2.4'
25soversion = libversion.split('.')[0]
26libsoup_api_name = '@0@-@1@'.format(meson.project_name(), apiversion)
27libversion_arr = libversion.split('.')
28darwin_version_major = libversion_arr[0].to_int()
29darwin_version_minor = libversion_arr[1].to_int()
30darwin_version_micro = libversion_arr[2].to_int()
31darwin_versions = [darwin_version_major + darwin_version_minor + 1, '@0@.@1@'.format(darwin_version_major + darwin_version_minor + 1, darwin_version_micro)]
32
33host_system = host_machine.system()
34
35# Needed for the gmtime_r check and for some system types availability.
36default_source_flag = [
37  '-D_DEFAULT_SOURCE'
38]
39
40add_project_arguments(default_source_flag, language: 'c')
41
42if host_system == 'sunos'
43      add_project_arguments('-D__EXTENSIONS__', language: 'c')
44      add_project_link_arguments('-lsocket', language: 'c')
45endif
46
47common_flags = [
48  '-DHAVE_CONFIG_H',
49]
50
51cc = meson.get_compiler('c')
52# Enable extra warnings if compiler supports them.
53if cc.get_id() == 'msvc'
54  common_flags += ['/FImsvc_recommended_pragmas.h']
55
56  # set the input encoding to utf-8
57  add_project_arguments(cc.get_supported_arguments(['/utf-8']), language: 'c')
58else
59  test_cflags = [
60      '-Wall',
61      '-Wmissing-include-dirs',
62      '-Wpointer-arith',
63      '-Winit-self',
64      '-Wdeclaration-after-statement',
65      '-Werror=missing-prototypes',
66      '-Werror=implicit-function-declaration',
67      '-Werror=aggregate-return',
68      '-Werror=format=2',
69      '-Wstrict-prototypes',
70      '-Wno-format-zero-length',
71  ]
72
73  common_flags += cc.get_supported_arguments(test_cflags)
74endif
75
76if cc.get_id() != 'msvc' and host_system == 'windows'
77  # For "%2hhx" sscanf format and the like
78  add_project_arguments('-D__USE_MINGW_ANSI_STDIO=1', language : 'c')
79endif
80
81add_project_arguments(common_flags, language : 'c')
82
83glib_required_version = '>= 2.58'
84glib_dep = dependency('glib-2.0', version : glib_required_version,
85                       fallback: ['glib', 'libglib_dep'])
86gobject_dep = dependency('gobject-2.0', version : glib_required_version,
87                       fallback: ['glib', 'libgobject_dep'])
88gio_dep = dependency('gio-2.0', version : glib_required_version,
89                       fallback: ['glib', 'libgio_dep'])
90
91glib_deps = [glib_dep, gobject_dep, gio_dep]
92
93sqlite_dep = dependency('sqlite3', required: false)
94
95# Fallback check for sqlite, not all platforms ship pkg-config file
96if not sqlite_dep.found()
97  sqlite_dep = cc.find_library('sqlite3',
98    has_headers : ['sqlite3.h', 'sqlite3ext.h'],
99    required: false)
100endif
101
102if not sqlite_dep.found()
103  sqlite_dep = subproject('sqlite').get_variable('sqlite_dep')
104endif
105
106libxml_dep = dependency('libxml-2.0', required: false)
107
108# Fallback check for libxml2, not all platforms ship pkg-config file
109if not libxml_dep.found()
110  # Note: The XML include dir needs to be within the INCLUDE envvar,
111  # such as <INCLUDEDIR>\libxml2
112  libxml2_libname = cc.get_id() == 'msvc' ? 'libxml2' : 'xml2'
113  libxml_dep = cc.find_library(libxml2_libname,
114    has_headers : 'libxml/tree.h',
115    required: false)
116endif
117
118if not libxml_dep.found()
119  libxml_dep = subproject('libxml2').get_variable('xml2lib_dep')
120endif
121
122cdata = configuration_data()
123
124brotlidec_dep = dependency('libbrotlidec', required : get_option('brotli'))
125if brotlidec_dep.found()
126  cdata.set('WITH_BROTLI', true)
127endif
128
129platform_deps = []
130hidden_visibility_flag = []
131is_static_library = get_option('default_library') == 'static'
132if not is_static_library
133  if host_machine.system() == 'windows'
134    platform_deps = [cc.find_library('ws2_32')]
135    cdata.set('DLL_EXPORT', true)
136    cdata.set('_SOUP_EXTERN', '__declspec(dllexport) extern')
137    if cc.get_id() != 'msvc'
138      hidden_visibility_flag += ['-fvisibility=hidden']
139    endif
140  else
141    cdata.set('_SOUP_EXTERN', '__attribute__((visibility("default"))) extern')
142    hidden_visibility_flag += ['-fvisibility=hidden']
143  endif
144endif
145
146libpsl_required_version = '>= 0.20'
147libpsl_dep = dependency('libpsl', version : libpsl_required_version,
148  fallback : ['libpsl', 'libpsl_dep'])
149
150if cc.has_function('gmtime_r', prefix : '#include <time.h>', args : default_source_flag)
151    cdata.set('HAVE_GMTIME_R', '1')
152endif
153
154###################
155# GIO TLS support #
156###################
157enable_tls_check = get_option('tls_check')
158if enable_tls_check
159  if gio_dep.type_name() == 'internal'
160    warning('TLS check was enabled but required dependency is internal')
161  else
162    check_gio_tls_src = '''#include <gio/gio.h>
163    int main(void) {
164      return !g_tls_backend_supports_tls (g_tls_backend_get_default ());
165    }
166    '''
167
168    rres = cc.run(check_gio_tls_src, name : 'GIO has real TLS support', dependencies : glib_deps)
169    assert(rres.compiled() and rres.returncode() == 0, 'libsoup requires glib-networking for TLS support')
170  endif
171endif
172
173libz_dep = dependency('zlib', required : false)
174if not libz_dep.found()
175  if cc.get_id() != 'msvc'
176    libz_dep = cc.find_library('z', required : false)
177  else
178    libz_dep = cc.find_library('zlib1', required : false)
179    if not libz_dep.found()
180      libz_dep = cc.find_library('zlib', required : false)
181    endif
182  endif
183  if not libz_dep.found() or not cc.has_header('zlib.h')
184    libz_dep = subproject('zlib').get_variable('zlib_dep')
185  endif
186endif
187
188#################################
189# Regression tests dependencies #
190#################################
191
192# The situation here is a little bit complicated. For running some of the tests
193# we need the Apache's httpd binary. As we want to know more about its
194# configuration we have to run it and parse the output. But here is the first
195# problem, because on Debian we can't run the binary unless the
196# /etc/apache2/envvars file is sourced, otherwise it ends with failure. The
197# recommended way to communicate with the Apache is the apachectl that passes
198# the arguments to httpd and also sources the envvars file. In the ideal world
199# we could use the apachectl to run the tests as well, but on Fedora any non
200# trivial call to it ends with the following error:
201#     Passing arguments to httpd using apachectl is no longer supported.
202#
203# The summary is that for the configuration parsing we will use the apachectl,
204# but for running the tests we will use the httpd binary.
205apachectl = find_program('apachectl', '/sbin/apachectl', '/usr/sbin/apachectl', required : false)
206# This abomination is a result of https://github.com/mesonbuild/meson/issues/1576
207apache_httpd2 = find_program('httpd2', 'httpd', 'apache2', 'apache',
208             '/sbin/httpd2', '/sbin/httpd', '/sbin/apache2', '/sbin/apache',
209             '/usr/sbin/httpd2', '/usr/sbin/httpd', '/usr/sbin/apache2', '/usr/sbin/apache',
210             required : false)
211have_apache=false
212apache_httpd2_version = ''
213if apache_httpd2.found() and apachectl.found()
214  apache_httpd2_version_raw = run_command(apachectl.path(), '-v')
215  # It seems that from version 2.4.39 apachectl doesn't take arguments, fallback
216  # to calling apache directly just in case.
217  if apache_httpd2_version_raw.returncode() != 0
218    apache_httpd2_version_raw = run_command(apache_httpd2.path(), '-v')
219  endif
220  if apache_httpd2_version_raw.returncode() == 0
221    apache_httpd2_version = apache_httpd2_version_raw.stdout().split('\n')[0]
222    apache_httpd2_version = apache_httpd2_version.split('/')[1].split(' ')[0]
223    if apache_httpd2_version.version_compare('>=2.4')
224      have_apache = true
225      cdata.set_quoted('APACHE_HTTPD', apache_httpd2.path())
226    else
227      message('Found ' + apache_httpd2_version + ', but at least 2.4 is needed - ignoring')
228    endif
229  endif
230endif
231
232if have_apache
233  apache_modules_dirs_out = run_command('get_apache_modules_dirs.py', apachectl.path())
234  have_apache = (apache_modules_dirs_out.returncode() == 0)
235  # Same as above, using apachectl might fail, try apache directly.
236  if not have_apache
237    apache_modules_dirs_out = run_command('get_apache_modules_dirs.py', apache_httpd2.path())
238    have_apache = (apache_modules_dirs_out.returncode() == 0)
239  endif
240  if have_apache
241    apache_modules_dirs = apache_modules_dirs_out.stdout().split(':')
242    message('Apache modules directory: ' + apache_modules_dirs[0])
243    cdata.set('APACHE_MODULE_DIR', apache_modules_dirs[0])
244    message('Apache SSL module directory: ' + apache_modules_dirs[1])
245    cdata.set('APACHE_SSL_MODULE_DIR', apache_modules_dirs[1])
246    message('Apache PHP module file: ' + apache_modules_dirs[2])
247    cdata.set('APACHE_PHP_MODULE_FILE', apache_modules_dirs[2])
248    message('Apache mod_unixd module directory: ' + (apache_modules_dirs[3] != '' ? apache_modules_dirs[3] : '(none)'))
249    cdata.set('IF_HAVE_MOD_UNIXD', apache_modules_dirs[3] != '' ? '' : '#')
250    cdata.set('HAVE_APACHE', have_apache)
251  else
252    message('Failed to locate necessary Apache modules for full test coverage')
253    message('stdout: ' + apache_modules_dirs_out.stdout())
254    message('stderr: ' + apache_modules_dirs_out.stderr())
255  endif
256endif
257
258have_php = false
259have_php_xmlrpc = false
260if have_apache
261  php = find_program('php', required : false)
262  message(cdata.get('APACHE_PHP_MODULE_FILE'))
263  if php.found() and cdata.get('APACHE_PHP_MODULE_FILE') != ''
264    have_php = true
265    php_xmlrpc = run_command(php, '-d', 'extension=xmlrpc', '-r', 'exit(function_exists("xmlrpc_server_create")?0:1);')
266    if php_xmlrpc.returncode() == 0
267      message('php-xmlrpc found')
268      have_php_xmlrpc = true
269      cdata.set('HAVE_PHP_XMLRPC', '1')
270    else
271      message('php-xmlrpc not found')
272    endif
273  endif
274  cdata.set('IF_HAVE_PHP', have_php ? '' : '#')
275  cdata.set('IF_HAVE_PHP_XMLRPC', have_php_xmlrpc ? '' : ';')
276endif
277
278tests_ready = have_apache and have_php and have_php_xmlrpc
279if not tests_ready
280  warning('Some regression tests will not be compiled due to missing libraries or modules. Please check the logs for more details.')
281endif
282
283##################
284# GSSAPI support #
285##################
286gssapi_opt = get_option('gssapi')
287enable_gssapi = false
288if cc.get_id() == 'msvc'
289  if host_machine.cpu_family() == 'x86'
290    gssapi_lib_type = '32'
291  else
292    gssapi_lib_type = '64'
293  endif
294  gssapi_lib = cc.find_library('gssapi' + gssapi_lib_type,
295    has_headers: 'gssapi/gssapi.h',
296    required: gssapi_opt)
297  if gssapi_lib.found()
298      enable_gssapi = true
299      add_project_link_arguments('gssapi@0@.lib'.format(gssapi_lib_type), language : 'c')
300  endif
301else
302  krb5_config_path = get_option('krb5_config')
303  if not meson.is_cross_build() and krb5_config_path == ''
304    krb5_config_path = 'krb5-config'
305  endif
306  krb5_config = find_program(krb5_config_path, required : gssapi_opt)
307  if krb5_config.found()
308    libs_output = run_command (krb5_config, '--libs', 'gssapi', check: gssapi_opt.enabled())
309    cflags_output = run_command (krb5_config, '--cflags', 'gssapi', check: gssapi_opt.enabled())
310    if libs_output.returncode() == 0 and cflags_output.returncode() == 0
311      enable_gssapi = true
312      add_project_link_arguments(libs_output.stdout().split(), language : 'c')
313      add_project_arguments(cflags_output.stdout().split(), language : 'c')
314    endif
315  endif
316endif
317
318if enable_gssapi
319  add_project_arguments('-DLIBSOUP_HAVE_GSSAPI=1', language : 'c')
320endif
321
322################
323# NTLM support #
324################
325# NTLM not supported on Windows
326if host_machine.system() != 'windows'
327  ntlm_auth = find_program(get_option('ntlm_auth'), required: get_option('ntlm'))
328
329  if ntlm_auth.found()
330    add_project_arguments('-DUSE_NTLM_AUTH=1', language : 'c')
331    add_project_arguments('-DNTLM_AUTH="' + ntlm_auth.path() + '"', language : 'c')
332  endif
333endif
334
335#################
336# GNOME support #
337#################
338enable_gnome = get_option('gnome')
339
340#########################
341# GObject introspection #
342#########################
343gir = find_program('g-ir-scanner', required: get_option('introspection'))
344enable_introspection = gir.found()
345
346############
347# Vala API #
348############
349vapi_opt = get_option('vapi')
350enable_vapi = add_languages('vala', required: vapi_opt)
351if enable_vapi and not enable_introspection
352  enable_vapi = false
353  if vapi_opt.enabled()
354    error('vapi support was requested, but introspection support is mandatory.')
355  endif
356endif
357
358configinc = include_directories('.')
359
360prefix = get_option('prefix')
361
362cdata.set_quoted('PACKAGE_VERSION', soup_version)
363cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
364cdata.set_quoted('GETTEXT_PACKAGE', libsoup_api_name)
365configure_file(output : 'config.h', configuration : cdata)
366
367subdir('libsoup')
368# xgettext is optional (on Windows for instance)
369if find_program('xgettext', required : false).found()
370  subdir('po')
371endif
372subdir('examples')
373
374if get_option('tests')
375  subdir('tests')
376 endif
377
378if get_option('gtk_doc')
379  srcdir = include_directories('libsoup')
380  subdir('docs/reference')
381endif
382