1 project('libsoup', 'c',
3 meson_version : '>=0.50',
5 default_options : 'c_std=c99')
7 gnome = import('gnome')
9 soup_version = meson.project_version()
10 version_arr = soup_version.split('.')
11 soup_version_major = version_arr[0]
12 soup_version_minor = version_arr[1]
13 soup_version_micro = version_arr[2]
15 # Before making a release, the libversion string should be modified.
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.
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.
25 soversion = libversion.split('.')[0]
26 libsoup_api_name = '@0@-@1@'.format(meson.project_name(), apiversion)
27 libversion_arr = libversion.split('.')
28 darwin_version_major = libversion_arr[0].to_int()
29 darwin_version_minor = libversion_arr[1].to_int()
30 darwin_version_micro = libversion_arr[2].to_int()
31 darwin_versions = [darwin_version_major + darwin_version_minor + 1, '@0@.@1@'.format(darwin_version_major + darwin_version_minor + 1, darwin_version_micro)]
33 host_system = host_machine.system()
35 # Needed for the gmtime_r check and for some system types availability.
36 default_source_flag = [
40 add_project_arguments(default_source_flag, language: 'c')
42 if host_system == 'sunos'
43 add_project_arguments('-D__EXTENSIONS__', language: 'c')
44 add_project_link_arguments('-lsocket', language: 'c')
51 cc = meson.get_compiler('c')
52 # Enable extra warnings if compiler supports them.
53 if cc.get_id() == 'msvc'
54 common_flags += ['/FImsvc_recommended_pragmas.h']
56 # set the input encoding to utf-8
57 add_project_arguments(cc.get_supported_arguments(['/utf-8']), language: 'c')
61 '-Wmissing-include-dirs',
64 '-Wdeclaration-after-statement',
65 '-Werror=missing-prototypes',
66 '-Werror=implicit-function-declaration',
67 '-Werror=aggregate-return',
69 '-Wstrict-prototypes',
70 '-Wno-format-zero-length',
73 common_flags += cc.get_supported_arguments(test_cflags)
76 if 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')
81 add_project_arguments(common_flags, language : 'c')
83 glib_required_version = '>= 2.58'
84 glib_dep = dependency('glib-2.0', version : glib_required_version,
85 fallback: ['glib', 'libglib_dep'])
86 gobject_dep = dependency('gobject-2.0', version : glib_required_version,
87 fallback: ['glib', 'libgobject_dep'])
88 gio_dep = dependency('gio-2.0', version : glib_required_version,
89 fallback: ['glib', 'libgio_dep'])
91 glib_deps = [glib_dep, gobject_dep, gio_dep]
93 sqlite_dep = dependency('sqlite3', required: false)
95 # Fallback check for sqlite, not all platforms ship pkg-config file
96 if not sqlite_dep.found()
97 sqlite_dep = cc.find_library('sqlite3',
98 has_headers : ['sqlite3.h'],
102 if not sqlite_dep.found()
103 sqlite_dep = subproject('sqlite').get_variable('sqlite_dep')
106 libxml_dep = dependency('libxml-2.0', required: false)
108 # Fallback check for libxml2, not all platforms ship pkg-config file
109 if 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',
118 if not libxml_dep.found()
119 libxml_dep = subproject('libxml2').get_variable('xml2lib_dep')
122 cdata = configuration_data()
124 brotlidec_dep = dependency('libbrotlidec', required : get_option('brotli'))
125 if brotlidec_dep.found()
126 cdata.set('WITH_BROTLI', true)
130 hidden_visibility_flag = []
131 is_static_library = get_option('default_library') == 'static'
132 if 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']
141 cdata.set('_SOUP_EXTERN', '__attribute__((visibility("default"))) extern')
142 hidden_visibility_flag += ['-fvisibility=hidden']
146 libpsl_required_version = '>= 0.20'
147 libpsl_dep = dependency('libpsl', version : libpsl_required_version,
148 fallback : ['libpsl', 'libpsl_dep'])
150 if cc.has_function('gmtime_r', prefix : '#include <time.h>', args : default_source_flag)
151 cdata.set('HAVE_GMTIME_R', '1')
155 libsysprof_capture_dep = dependency('sysprof-capture-4',
156 required: get_option('sysprof'),
158 'enable_examples=false',
160 'enable_tests=false',
161 'enable_tools=false',
163 'with_sysprofd=none',
166 fallback: ['sysprof', 'libsysprof_capture_dep'],
168 cdata.set('HAVE_SYSPROF', libsysprof_capture_dep.found())
173 enable_tls_check = get_option('tls_check')
175 if gio_dep.type_name() == 'internal'
176 warning('TLS check was enabled but required dependency is internal')
178 check_gio_tls_src = '''#include <gio/gio.h>
180 return !g_tls_backend_supports_tls (g_tls_backend_get_default ());
184 rres = cc.run(check_gio_tls_src, name : 'GIO has real TLS support', dependencies : glib_deps)
185 assert(rres.compiled() and rres.returncode() == 0, 'libsoup requires glib-networking for TLS support')
189 libz_dep = dependency('zlib', required : false)
190 if not libz_dep.found()
191 if cc.get_id() != 'msvc'
192 libz_dep = cc.find_library('z', required : false)
194 libz_dep = cc.find_library('zlib1', required : false)
195 if not libz_dep.found()
196 libz_dep = cc.find_library('zlib', required : false)
199 if not libz_dep.found() or not cc.has_header('zlib.h')
200 libz_dep = subproject('zlib').get_variable('zlib_dep')
204 #################################
205 # Regression tests dependencies #
206 #################################
208 # The situation here is a little bit complicated. For running some of the tests
209 # we need the Apache's httpd binary. As we want to know more about its
210 # configuration we have to run it and parse the output. But here is the first
211 # problem, because on Debian we can't run the binary unless the
212 # /etc/apache2/envvars file is sourced, otherwise it ends with failure. The
213 # recommended way to communicate with the Apache is the apachectl that passes
214 # the arguments to httpd and also sources the envvars file. In the ideal world
215 # we could use the apachectl to run the tests as well, but on Fedora any non
216 # trivial call to it ends with the following error:
217 # Passing arguments to httpd using apachectl is no longer supported.
219 # The summary is that for the configuration parsing we will use the apachectl,
220 # but for running the tests we will use the httpd binary.
221 apachectl = find_program('apachectl', '/sbin/apachectl', '/usr/sbin/apachectl', required : false)
222 # This abomination is a result of https://github.com/mesonbuild/meson/issues/1576
223 apache_httpd2 = find_program('httpd2', 'httpd', 'apache2', 'apache',
224 '/sbin/httpd2', '/sbin/httpd', '/sbin/apache2', '/sbin/apache',
225 '/usr/sbin/httpd2', '/usr/sbin/httpd', '/usr/sbin/apache2', '/usr/sbin/apache',
228 apache_httpd2_version = ''
229 if apache_httpd2.found() and apachectl.found()
230 apache_httpd2_version_raw = run_command(apachectl.path(), '-v')
231 # It seems that from version 2.4.39 apachectl doesn't take arguments, fallback
232 # to calling apache directly just in case.
233 if apache_httpd2_version_raw.returncode() != 0
234 apache_httpd2_version_raw = run_command(apache_httpd2.path(), '-v')
236 if apache_httpd2_version_raw.returncode() == 0
237 apache_httpd2_version = apache_httpd2_version_raw.stdout().split('\n')[0]
238 apache_httpd2_version = apache_httpd2_version.split('/')[1].split(' ')[0]
239 if apache_httpd2_version.version_compare('>=2.4')
241 cdata.set_quoted('APACHE_HTTPD', apache_httpd2.path())
243 message('Found ' + apache_httpd2_version + ', but at least 2.4 is needed - ignoring')
249 apache_modules_dirs_out = run_command('get_apache_modules_dirs.py', apachectl.path())
250 have_apache = (apache_modules_dirs_out.returncode() == 0)
251 # Same as above, using apachectl might fail, try apache directly.
253 apache_modules_dirs_out = run_command('get_apache_modules_dirs.py', apache_httpd2.path())
254 have_apache = (apache_modules_dirs_out.returncode() == 0)
257 apache_modules_dirs = apache_modules_dirs_out.stdout().split(':')
258 message('Apache modules directory: ' + apache_modules_dirs[0])
259 cdata.set('APACHE_MODULE_DIR', apache_modules_dirs[0])
260 message('Apache SSL module directory: ' + apache_modules_dirs[1])
261 cdata.set('APACHE_SSL_MODULE_DIR', apache_modules_dirs[1])
262 message('Apache PHP module file: ' + apache_modules_dirs[2])
263 cdata.set('APACHE_PHP_MODULE_FILE', apache_modules_dirs[2])
264 message('Apache mod_unixd module directory: ' + (apache_modules_dirs[3] != '' ? apache_modules_dirs[3] : '(none)'))
265 cdata.set('IF_HAVE_MOD_UNIXD', apache_modules_dirs[3] != '' ? '' : '#')
266 cdata.set('HAVE_APACHE', have_apache)
268 message('Failed to locate necessary Apache modules for full test coverage')
269 message('stdout: ' + apache_modules_dirs_out.stdout())
270 message('stderr: ' + apache_modules_dirs_out.stderr())
275 have_php_xmlrpc = false
277 php = find_program('php', required : false)
278 message(cdata.get('APACHE_PHP_MODULE_FILE'))
279 if php.found() and cdata.get('APACHE_PHP_MODULE_FILE') != ''
281 php_xmlrpc = run_command(php, '-d', 'extension=xmlrpc', '-r', 'exit(function_exists("xmlrpc_server_create")?0:1);')
282 if php_xmlrpc.returncode() == 0
283 message('php-xmlrpc found')
284 have_php_xmlrpc = true
285 cdata.set('HAVE_PHP_XMLRPC', '1')
287 message('php-xmlrpc not found')
290 cdata.set('IF_HAVE_PHP', have_php ? '' : '#')
291 cdata.set('IF_HAVE_PHP_XMLRPC', have_php_xmlrpc ? '' : ';')
294 tests_ready = have_apache and have_php and have_php_xmlrpc
296 warning('Some regression tests will not be compiled due to missing libraries or modules. Please check the logs for more details.')
302 gssapi_opt = get_option('gssapi')
303 enable_gssapi = false
304 if cc.get_id() == 'msvc'
305 if host_machine.cpu_family() == 'x86'
306 gssapi_lib_type = '32'
308 gssapi_lib_type = '64'
310 gssapi_lib = cc.find_library('gssapi' + gssapi_lib_type,
311 has_headers: 'gssapi/gssapi.h',
312 required: gssapi_opt)
313 if gssapi_lib.found()
315 add_project_link_arguments('gssapi@0@.lib'.format(gssapi_lib_type), language : 'c')
318 krb5_config_path = get_option('krb5_config')
319 if not meson.is_cross_build() and krb5_config_path == ''
320 krb5_config_path = 'krb5-config'
322 krb5_config = find_program(krb5_config_path, required : gssapi_opt)
323 if krb5_config.found()
324 libs_output = run_command (krb5_config, '--libs', 'gssapi', check: gssapi_opt.enabled())
325 cflags_output = run_command (krb5_config, '--cflags', 'gssapi', check: gssapi_opt.enabled())
326 if libs_output.returncode() == 0 and cflags_output.returncode() == 0
328 add_project_link_arguments(libs_output.stdout().split(), language : 'c')
329 add_project_arguments(cflags_output.stdout().split(), language : 'c')
335 add_project_arguments('-DLIBSOUP_HAVE_GSSAPI=1', language : 'c')
341 # NTLM not supported on Windows
342 if host_machine.system() != 'windows'
343 ntlm_auth = find_program(get_option('ntlm_auth'), required: get_option('ntlm'))
346 add_project_arguments('-DUSE_NTLM_AUTH=1', language : 'c')
347 add_project_arguments('-DNTLM_AUTH="' + ntlm_auth.path() + '"', language : 'c')
354 enable_gnome = get_option('gnome')
356 #########################
357 # GObject introspection #
358 #########################
359 gir = find_program('g-ir-scanner', required: get_option('introspection'))
360 enable_introspection = gir.found()
365 vapi_opt = get_option('vapi')
366 enable_vapi = add_languages('vala', required: vapi_opt)
367 if enable_vapi and not enable_introspection
369 if vapi_opt.enabled()
370 error('vapi support was requested, but introspection support is mandatory.')
374 configinc = include_directories('.')
376 prefix = get_option('prefix')
378 cdata.set_quoted('PACKAGE_VERSION', soup_version)
379 cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
380 cdata.set_quoted('GETTEXT_PACKAGE', libsoup_api_name)
381 configure_file(output : 'config.h', configuration : cdata)
384 # xgettext is optional (on Windows for instance)
385 if find_program('xgettext', required : false).found()
390 if get_option('tests')
394 if get_option('gtk_doc')
395 srcdir = include_directories('libsoup')
396 subdir('docs/reference')