1project( 2 'libxml2', 3 'c', 4 version: '2.13.0', 5 license: 'MIT', 6 default_options: ['buildtype=debug', 'warning_level=3'], 7 meson_version: '>= 0.61', 8) 9 10v_array = meson.project_version().split('.') 11v_maj = v_array[0] 12v_min = v_array[1] 13v_mic = v_array[2] 14v_nbr = v_maj.to_int() * 10000 + v_min.to_int() * 100 + v_mic.to_int() 15v_extra = '' 16r = run_command('git', 'describe', check: false) 17if (r.returncode() == 0) 18 v_extra = '-GIT' + r.stdout().strip() 19endif 20 21# install paths 22dir_prefix = get_option('prefix') 23dir_bin = dir_prefix / get_option('bindir') 24dir_include = dir_prefix / get_option('includedir') 25dir_pkginclude = dir_include / meson.project_name() 26dir_lib = dir_prefix / get_option('libdir') 27dir_data = dir_prefix / get_option('datadir') 28dir_doc = dir_data / 'doc' / 'libxml2' 29dir_locale = dir_prefix / get_option('localedir') 30 31# host 32 33host_os = host_machine.system() 34 35cygwin = 'cygwin' 36windows = 'windows' 37sys_cygwin = cygwin.contains(host_os) 38sys_windows = windows.contains(host_os) 39 40libxml2_cflags = [] 41xml_cflags = '' 42dep_args = [] 43 44if sys_cygwin or sys_windows 45 if get_option('default_library') == 'static' 46 xml_cflags = '-DLIBXML_STATIC' 47 libxml2_cflags += '-DLIBXML_STATIC' 48 dep_args += '-DLIBXML_STATIC' 49 endif 50endif 51 52# binaries 53cc = meson.get_compiler('c') 54 55# options 56want_c14n = get_option('c14n') 57want_catalog = get_option('catalog') 58want_debug = get_option('debuging') 59want_history = get_option('history') 60want_html = get_option('html') 61want_http = get_option('http') 62want_ipv6 = get_option('ipv6') 63want_iso8859x = get_option('iso8859x') 64want_legacy = get_option('legacy') 65want_output = get_option('output') 66want_pattern = get_option('pattern') 67want_push = get_option('push') 68want_python = get_option('python') 69want_reader = get_option('reader') 70want_readline = get_option('readline') 71want_regexps = get_option('regexps') 72want_sax1 = get_option('sax1') 73want_schemas = get_option('schemas') 74want_schematron = get_option('schematron') 75want_thread_alloc = get_option('thread-alloc') 76want_tls = get_option('tls') 77want_tree = get_option('tree') 78want_valid = get_option('valid') 79want_writer = get_option('writer') 80want_xinclude = get_option('xinclude') 81want_xpath = get_option('xpath') 82want_xptr = get_option('xptr') 83 84# TODO: Options should be three-valued: "yes", "no", default 85 86# TODO: Legacy defaults 87 88# hard dependencies on options 89 90if want_c14n == true 91 if want_output == false 92 message('-Dc14n=true overrides -Doutput') 93 endif 94 want_output = true 95 if want_xpath == false 96 message('-Dc14n=true overrides -Dxpath') 97 endif 98 want_xpath = true 99endif 100 101if want_schemas == true 102 if want_pattern == false 103 message('-Dschemas=true overrides -Dpattern') 104 endif 105 want_pattern = true 106 if want_regexps == false 107 message('-Dschemas=true overrides -Dregexps') 108 endif 109 want_regexps = true 110endif 111 112if want_schematron == true 113 if want_pattern == false 114 message('-Dschematron=true overrides -Dpattern') 115 endif 116 want_pattern = true 117 if want_tree == false 118 message('-Dschematron=true overrides -Dtree') 119 endif 120 want_tree = true 121 if want_xpath == false 122 message('-Dschematron=true overrides -Dxpath') 123 endif 124 want_xpath = true 125endif 126 127if want_reader == true 128 if want_push == false 129 message('-Dreader=true overrides -Dpush') 130 endif 131 want_push = true 132 if want_tree == false 133 message('-Dreader=true overrides -Dtree') 134 endif 135 want_tree = true 136endif 137 138if want_writer == true 139 if want_output == false 140 message('-Dwriter=true overrides -Doutput') 141 endif 142 want_output = true 143 if want_push == false 144 message('-Dwriter=true overrides -Dpush') 145 endif 146 want_push = true 147endif 148 149if want_xinclude == true 150 if want_xpath == false 151 message('-Dxinclude=true overrides -Dxpath') 152 endif 153 want_xpath = true 154endif 155 156if want_xptr == true 157 if want_xpath == false 158 message('-Dxptr=true overrides -Dxpath') 159 endif 160 want_xpath = true 161endif 162 163# minimum dependencies 164 165if get_option('minimum') 166 # TODO: This is should allow other options 167 want_c14n = false 168 want_catalog = false 169 want_debug = false 170 want_history = false 171 want_html = false 172 want_http = false 173 want_ipv6 = false 174 want_iso8859x = false 175 want_output = false 176 want_pattern = false 177 want_push = false 178 want_python = false 179 want_reader = false 180 want_readline = false 181 want_regexps = false 182 want_sax1 = false 183 want_schemas = false 184 want_schematron = false 185 want_thread_alloc = false 186 want_tree = false 187 want_valid = false 188 want_writer = false 189 want_xinclude = false 190 want_xpath = false 191 want_xptr = false 192else 193 # Disable dependent modules 194 if want_output == false 195 want_c14n = false 196 want_writer = false 197 endif 198 if want_pattern == false 199 want_schemas = false 200 want_schematron = false 201 endif 202 if want_push == false 203 want_reader = false 204 want_writer = false 205 endif 206 if want_regexps == false 207 want_schemas = false 208 endif 209 if want_tree == false 210 want_reader = false 211 want_schematron = false 212 endif 213 if want_xpath == false 214 want_c14n = false 215 want_schematron = false 216 want_xinclude = false 217 want_xptr = false 218 endif 219endif 220 221cflags_try = [] 222 223### workaround for native compilers, see configure.ac 224if cc.get_argument_syntax() == 'gcc' 225 cflags_try += [ 226 '-Wshadow', 227 '-Wpointer-arith', 228 '-Wcast-align', 229 '-Wwrite-strings', 230 '-Wstrict-prototypes', 231 '-Wmissing-prototypes', 232 '-Wno-long-long', 233 '-Wno-format-extra-args', 234 ] 235 236 if host_machine.cpu_family() == 'alpha' 237 cflags_try += '-mieee' 238 endif 239else 240 if host_machine.cpu_family() == 'alpha' 241 cflags_try += '-ieee' 242 elif host_machine.cpu_family() == 'parisc' 243 cflags_try += '-Wp,-H30000' 244 endif 245endif 246 247foreach cf : cflags_try 248 if cc.has_argument(cf) 249 libxml2_cflags += cf 250 endif 251endforeach 252 253# configuration 254# 255# X : done 256# N : not done 257# 258# [X] config.h.in 259# [X] include/libxml/xmlversion.h.in 260# [N] libxml-2.0-uninstalled.pc.in 261# [X] libxml-2.0.pc.in 262# [X] libxml2-config.cmake.in 263# [X] python/setup.py.in 264# [N] xml2-config.in 265 266## config.h 267config_h = configuration_data() 268config_h.set_quoted('PACKAGE_NAME', meson.project_name()) 269config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) 270config_h.set_quoted('PACKAGE_BIN_DIR', dir_bin) 271config_h.set_quoted('PACKAGE_LIB_DIR', dir_lib) 272config_h.set_quoted('PACKAGE_DATA_DIR', dir_data) 273config_h.set_quoted('LOCALEDIR', dir_locale) 274 275# header files 276xml_check_headers = [ 277 'stdint.h', 278 'fcntl.h', 279 'unistd.h', 280 'sys/stat.h', 281 'sys/mman.h', 282 'sys/socket.h', 283 'netinet/in.h', 284 'arpa/inet.h', 285 'netdb.h', 286 'sys/select.h', 287 'poll.h', 288 'sys/time.h', 289 'sys/timeb.h', 290 'dl.h', 291 'dlfcn.h', 292 'glob.h', 293] 294 295foreach header : xml_check_headers 296 if cc.has_header(header) 297 config_h.set10('HAVE_' + header.underscorify().to_upper(), true) 298 endif 299endforeach 300 301# library functions 302xml_check_functions = [ 303 # fct | header 304 ['gettimeofday', 'sys/time.h'], 305 ['ftime', 'sys/timeb.h'], 306 ['stat', 'sys/stat.h'], 307 ['mmap', 'sys/mman.h'], 308 ['munmap', 'sys/mman.h'], 309] 310 311foreach function : xml_check_functions 312 if cc.has_header_symbol(function[1], function[0]) 313 config_h.set10('HAVE_' + function[0].to_upper(), true) 314 endif 315endforeach 316 317# library 318 319config_dir = [include_directories('.'), include_directories('include')] 320 321## dependencies 322 323xml_deps = [] 324 325### math library 326if sys_windows == false 327 m_dep = cc.find_library('m', required: false) 328 if m_dep.found() 329 xml_deps += m_dep 330 endif 331endif 332 333### thread local storage 334support_tls = true 335if want_tls == true 336 tls_src = ''' 337#include <threads.h> 338int main() 339{ 340 _Thread_local int v; 341 return 0; 342} 343 ''' 344 res = cc.compiles(tls_src, name: '_Thread_local') 345 if res == true 346 config_h.set('XML_THREAD_LOCAL', '_Thread_local') 347 else 348 tls_src = ''' 349int main() 350{ 351 __thread int v; 352 return 0; 353} 354 ''' 355 res = cc.compiles(tls_src, name: '__thread') 356 if res == true 357 config_h.set('XML_THREAD_LOCAL', '__thread') 358 else 359 tls_src = ''' 360int main() 361{ 362 __declspec(thread) int v; 363 return 0; 364} 365 ''' 366 res = cc.compiles(tls_src, name: '__declspec(thread)') 367 if res == true 368 config_h.set('XML_THREAD_LOCAL', '__declspec(thread)') 369 else 370 want_tls = false 371 support_tls = false 372 endif 373 endif 374 endif 375endif 376 377### __attribute__((destructor)) 378if cc.has_function_attribute('destructor') 379 config_h.set10('HAVE_ATTRIBUTE_DESTRUCTOR', true) 380 config_h.set('ATTRIBUTE_DESTRUCTOR', '__attribute__((destructor))') 381endif 382 383### DSO support 384if sys_cygwin == true 385 module_extension = '.dll' 386elif sys_windows == true 387 module_extension = '.dll' 388else 389 module_extension = '.so' 390endif 391 392dl_dep = dependency('', required: false) 393if not get_option('minimum') 394 if host_machine.system() != 'windows' 395 if meson.version().version_compare('>=0.62') 396 dl_dep = dependency('dl', required: get_option('modules')) 397 else 398 dl_dep = cc.find_library('dl', required: get_option('modules')) 399 endif 400 if dl_dep.found() 401 config_h.set10('HAVE_DLOPEN', true) 402 xml_deps += dl_dep 403 endif 404 elif get_option('modules').allowed() 405 dl_dep = declare_dependency() 406 endif 407endif 408 409### threads 410threads_dep = dependency('', required: false) 411if not get_option('minimum') 412 if host_machine.system() != 'windows' 413 threads_dep = dependency('threads', required: get_option('threads')) 414 if threads_dep.found() 415 config_h.set10('HAVE_PTHREAD_H', true) 416 xml_deps += threads_dep 417 endif 418 elif get_option('threads').allowed() 419 threads_dep = declare_dependency() 420 endif 421endif 422 423want_thread_alloc = threads_dep.found() 424 425### xmllint shell history 426xmllint_deps = [] 427if want_history == true and want_readline == true 428 termlib_lib = ['ncurses', 'curses', 'termcap', 'terminfo', 'termlib'] 429 430 foreach tl : termlib_lib 431 termlib_dep = cc.find_library(tl) 432 if ( 433 termlib_dep.found() 434 and cc.has_function('tputs', dependencies: termlib_dep) 435 ) 436 xmllint_deps += termlib_dep 437 config_h.set10('HAVE_LIB' + tl.underscorify().to_upper(), true) 438 break 439 endif 440 endforeach 441 442 history_dep = dependency('history', required: false) 443 if history_dep.found() 444 xmllint_deps += history_dep 445 config_h.set10('HAVE_LIBHISTORY', true) 446 endif 447 448 readline_dep = dependency('readline', required: false) 449 if readline_dep.found() 450 xmllint_deps += readline_dep 451 config_h.set10('HAVE_LIBREADLINE', true) 452 endif 453endif 454 455### crypto 456if sys_windows == true 457 bcrypt_dep = cc.find_library('bcrypt', required: true) 458 xml_deps += bcrypt_dep 459endif 460 461### inet 462if want_http == true 463 if sys_windows == true 464 ws2_dep = cc.find_library('ws2_32', required: true) 465 xml_deps += ws2_dep 466 else 467 has_in_libc = cc.has_function('gethostbyname') 468 if has_in_libc == false 469 nsl_dep = cc.find_library('nsl', required: true) 470 if nsl_dep.found() 471 has_in_nsl = cc.has_function( 472 'gethostbyname', 473 dependencies: nsl_dep, 474 required: false, 475 ) 476 if has_in_nsl == true 477 xml_deps += nsl_dep 478 endif 479 endif 480 endif 481 endif 482 483 ### socket length 484 socklen_src = ''' 485#include <stddef.h> 486#ifdef _WIN32 487 #include <ws2tcpip.h> 488#else 489 #include <sys/socket.h> 490#endif 491int main() 492{ 493 (void)getsockopt (1, 1, 1, NULL, (socklen_t *)NULL); 494 return 0; 495} 496 ''' 497 res = cc.compiles(socklen_src, name: 'socket length as socklen_t') 498 if res == true 499 config_h.set('XML_SOCKLEN_T', 'socklen_t') 500 else 501 socklen_src = ''' 502#include <stddef.h> 503#include <sys/socket.h> 504int main() 505{ 506 (void)getsockopt (1, 1, 1, NULL, (size_t *)NULL); 507 return 0; 508} 509 ''' 510 res = cc.compiles(socklen_src, name: 'socket length as size_t') 511 if res == true 512 config_h.set('XML_SOCKLEN_T', 'size_t') 513 else 514 socklen_src = ''' 515#include <stddef.h> 516#include <sys/socket.h> 517int main() 518{ 519 (void)getsockopt (1, 1, 1, NULL, (int *)NULL); 520 return 0; 521} 522 ''' 523 res = cc.compiles(socklen_src, name: 'socket length as int') 524 if res == false 525 message('could not determine socket length type, use int') 526 endif 527 config_h.set('XML_SOCKLEN_T', 'int') 528 endif 529 endif 530 531 if want_ipv6 == true 532 ### IPV6 on Windows has been supported since Windows XP SP1 (around 2003) 533 ### see: 534 ### https://learn.microsoft.com/en-us/windows/win32/winsock/ipv6-support-2 535 ### nevertheless, we check it like autotools 536 ipv6_src = ''' 537#ifdef _WIN32 538#include <winsock2.h> 539#else 540#include <sys/socket.h> 541#ifdef HAVE_NETDB_H 542#include <netdb.h> 543#endif 544#endif 545int main() 546{ 547 struct sockaddr_storage ss; 548 socket(AF_INET6, SOCK_STREAM, 0); 549 getaddrinfo(0, 0, 0, 0); 550 return 0; 551} 552 ''' 553 res = cc.compiles(ipv6_src, name: 'support for IPV6') 554 if res == true 555 config_h.set10('SUPPORT_IP6', true) 556 endif 557 endif 558endif 559 560### zlib 561if not get_option('minimum') 562 zlib_dep = dependency('zlib', required: get_option('zlib')) 563else 564 zlib_dep = dependency('', required: false) 565endif 566xml_deps += zlib_dep 567 568### lzma 569if not get_option('minimum') 570 lzma_dep = dependency('liblzma', required: get_option('lzma')) 571else 572 lzma_dep = dependency('', required: false) 573endif 574xml_deps += lzma_dep 575 576### iconv 577if not get_option('minimum') 578 iconv_dep = dependency('iconv', required: get_option('iconv')) 579else 580 iconv_dep = dependency('', required: false) 581endif 582xml_deps += iconv_dep 583 584if not iconv_dep.found() and want_iso8859x == false 585 want_iso8859x = false 586else 587 want_iso8859x = true 588endif 589 590# icu 591icu_dep = dependency('icu-i18n', method: 'pkg-config', required: get_option('icu')) 592if icu_dep.found() 593 def_var = icu_dep.get_variable(pkgconfig: 'DEFS') 594 config_dir += include_directories(def_var) 595 xml_deps += icu_dep 596endif 597 598subdir('include/libxml') 599 600# Set config_h after all subdirs and dependencies have set values 601 602configure_file(output: 'config.h', configuration: config_h) 603 604## libxml2 library 605 606xml_src = [ 607 'buf.c', 608 'chvalid.c', 609 'dict.c', 610 'entities.c', 611 'encoding.c', 612 'error.c', 613 'globals.c', 614 'hash.c', 615 'list.c', 616 'parser.c', 617 'parserInternals.c', 618 'SAX2.c', 619 'threads.c', 620 'tree.c', 621 'uri.c', 622 'valid.c', 623 'xmlIO.c', 624 'xmlmemory.c', 625 'xmlstring.c', 626] 627 628xml_opt_src = [ 629 [want_c14n, ['c14n.c']], 630 [want_catalog, ['catalog.c']], 631 [want_debug, ['debugXML.c']], 632 [want_html, ['HTMLparser.c', 'HTMLtree.c']], 633 [want_http, ['nanohttp.c']], 634 [want_legacy, ['legacy.c']], 635 [lzma_dep.found(), ['xzlib.c']], 636 [dl_dep.found(), ['xmlmodule.c']], 637 [want_output, ['xmlsave.c']], 638 [want_pattern, ['pattern.c']], 639 [want_reader, ['xmlreader.c']], 640 [want_regexps, ['xmlregexp.c', 'xmlunicode.c']], 641 [want_sax1, ['SAX.c']], 642 [want_schemas, ['relaxng.c', 'xmlschemas.c', 'xmlschemastypes.c']], 643 [want_schemas and not want_xpath, ['xpath.c']], 644 [want_schematron, ['schematron.c']], 645 [want_writer, ['xmlwriter.c']], 646 [want_xinclude, ['xinclude.c']], 647 [want_xpath, ['xpath.c']], 648 [want_xptr, ['xlink.c', 'xpointer.c']], 649] 650 651foreach file : xml_opt_src 652 want = file[0] 653 src = file[1] 654 if want == true 655 if src.length() > 1 656 foreach s : src 657 xml_src += s 658 endforeach 659 else 660 xml_src += src 661 endif 662 endif 663endforeach 664 665xml_lib = library( 666 'xml2', 667 files(xml_src), 668 c_args: libxml2_cflags, 669 dependencies: xml_deps, 670 include_directories: config_dir, 671 install: true, 672 version: meson.project_version(), 673) 674 675dep_inc = include_directories('include') 676xml_dep = declare_dependency(include_directories: dep_inc, link_with: xml_lib, compile_args: dep_args) 677 678meson.override_dependency('libxml-2.0', xml_dep) 679 680## xmllint tool 681 682executable( 683 'xmllint', 684 files('xmllint.c'), 685 dependencies: [xml_dep, xmllint_deps], 686 include_directories: config_dir, 687 install: true, 688) 689 690## xmlcatalog tool 691 692executable( 693 'xmlcatalog', 694 files('xmlcatalog.c'), 695 dependencies: [xml_dep, xmllint_deps], 696 include_directories: config_dir, 697 install: true, 698) 699 700## testdso module 701 702testdso_mod = shared_module( 703 'testdso', 704 files('testdso.c'), 705 build_rpath: get_option('libdir'), 706 include_directories: config_dir, 707 name_prefix: '', 708) 709 710## tests 711 712checks = [ 713 'runsuite', 714 'runtest', 715 'runxmlconf', 716# Disabled for now, see #694 717# 'testModule', 718 'testThreads', 719 'testapi', 720 'testchar', 721 'testdict', 722 'testlimits', 723 'testparser', 724 'testrecurse', 725] 726 727foreach check : checks 728 exe = executable( 729 check, 730 files(check + '.c'), 731 dependencies: [threads_dep, xml_dep], 732 include_directories: config_dir, 733 ) 734 if check != 'testlimits' 735 test(check, exe, timeout: 0, workdir: meson.current_source_dir()) 736 endif 737endforeach 738 739subdir('example') 740subdir('doc') 741 742if want_python == true 743 subdir('python') 744endif 745 746## pc files 747 748pkgmod = import('pkgconfig') 749 750pkgmod.generate( 751 xml_lib, 752 description: 'libXML library version2.', 753 filebase: 'libxml-2.0', 754 name: 'libXML', 755 variables: 'modules=' + dl_dep.found().to_string('1', '0'), 756) 757 758## libxml2-config.cmake file 759 760config_cmake = configuration_data() 761config_cmake.set('LIBXML_MAJOR_VERSION', v_maj) 762config_cmake.set('LIBXML_MINOR_VERSION', v_min) 763config_cmake.set('LIBXML_MICRO_VERSION', v_mic) 764config_cmake.set('VERSION', meson.project_version()) 765config_cmake.set('WITH_ICONV', iconv_dep.found().to_int().to_string()) 766config_cmake.set('WITH_ICU', icu_dep.found().to_int().to_string()) 767config_cmake.set('WITH_LZMA', lzma_dep.found().to_int().to_string()) 768config_cmake.set('WITH_MODULES', dl_dep.found().to_int().to_string()) 769config_cmake.set('WITH_THREADS', threads_dep.found().to_int().to_string()) 770config_cmake.set('WITH_ZLIB', zlib_dep.found().to_int().to_string()) 771config_cmake.set('XML_CFLAGS', xml_cflags) 772configure_file( 773 input: 'libxml2-config.cmake.in', 774 output: 'libxml2-config.cmake', 775 configuration: config_cmake, 776 install_dir: dir_lib / 'cmake' / 'libxml2', 777) 778 779install_data(files('libxml.m4'), install_dir: dir_data / 'aclocal') 780 781if support_tls == false 782 message('===============================================================') 783 message('WARNING: Your C compiler appears to not support thread-local') 784 message('storage. Future versions of libxml2 will require this feature') 785 message('for multi-threading.') 786 message('===============================================================\n', 787 ) 788endif 789 790# summary 791 792summary( 793 { 794 'OS': host_os, 795 'c14n': want_c14n, 796 'catalog': want_catalog, 797 'debug': want_debug, 798 'history': want_history, 799 'html': want_html, 800 'http': want_http, 801 'iconv': iconv_dep.found(), 802 'icu': icu_dep.found(), 803 'ipv6': want_ipv6, 804 'iso8859x': want_iso8859x, 805 'legacy': want_legacy, 806 'lzma': lzma_dep.found(), 807 'modules': dl_dep.found(), 808 'output': want_output, 809 'pattern': want_pattern, 810 'push': want_push, 811 'python': want_python, 812 'reader': want_reader, 813 'readline': want_readline, 814 'regexps': want_regexps, 815 'sax1': want_sax1, 816 'schemas': want_schemas, 817 'schematron': want_schematron, 818 'threads': threads_dep.found(), 819 'thread-alloc': want_thread_alloc, 820 'tls': want_tls, 821 'tree': want_tree, 822 'valid': want_valid, 823 'writer': want_writer, 824 'xinclude': want_xinclude, 825 'xpath': want_xpath, 826 'xptr': want_xptr, 827 'zlib': zlib_dep.found(), 828 }, 829 section: 'Configuration Options Summary:', 830) 831