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