diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 93b562a3..7fb9c8c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -274,6 +274,18 @@ cmake:msvc:v141:x86:static: BUILD_SHARED_LIBS: "OFF" SUFFIX: static +meson: + image: registry.gitlab.gnome.org/gnome/libxml2 + script: + - sh .gitlab-ci/test_meson.sh + +cmake:linux:gcc:shared: + extends: .cmake:linux + variables: + BUILD_SHARED_LIBS: "ON" + CC: gcc + SUFFIX: linux-gcc-shared + pages: script: - mkdir -p public diff --git a/.gitlab-ci/test_meson.sh b/.gitlab-ci/test_meson.sh new file mode 100644 index 00000000..3e815fd6 --- /dev/null +++ b/.gitlab-ci/test_meson.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -e + +# compile with the following warnings: +# --warnlevel 3 : passes to the compiler -Wall -Wextra -Wpedantic +# --werror : passes to the compiler -Werror +# --default-library : can be 'shared', 'static' or 'both' +meson setup \ + --warnlevel 3 \ + --werror \ + --buildtype=debugoptimized \ + --default-library shared \ + builddir + +ninja -C builddir test + diff --git a/Makefile.am b/Makefile.am index 441cf5f2..3e8de7b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -387,7 +387,8 @@ EXTRA_DIST = Copyright check-xml-test-suite.py gentest.py \ dbgen.pl dbgenattr.pl \ libxml2.syms timsort.h \ README.zOS README.md \ - CMakeLists.txt config.h.cmake.in libxml2-config.cmake.cmake.in + CMakeLists.txt config.h.cmake.in libxml2-config.cmake.cmake.in \ + meson.build meson_options.txt pkgconfigdir = $(libdir)/pkgconfig diff --git a/README.md b/README.md index 8ffac536..716cb112 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ This code is released under the MIT License, see the Copyright file. ## Build instructions -libxml2 can be built with GNU Autotools, CMake, or several other build -systems in platform-specific subdirectories. +libxml2 can be built with GNU Autotools, CMake, meson or several other +build systems in platform-specific subdirectories. ### Autotools (for POSIX systems like Linux, BSD, macOS) @@ -121,6 +121,25 @@ Common CMake options include: You can also open the libxml source directory with its CMakeLists.txt directly in various IDEs such as CLion, QtCreator, or Visual Studio. +### Meson + +Libxml can also be built with meson. Without option, simply call + +meson setup builddir +ninja -C builddir + +To add options, see the meson_options.txt file. For example: + +meson setup -Dprefix=$prefix -Dftp=true -Dhistory=true -Dicu=true -Dhttp=true builddir + +To install libxml: + +ninja -C builddir install + +To launch tests: + +meson test -C builddir + ## Dependencies Libxml does not require any other libraries. A platform with somewhat diff --git a/doc/Makefile.am b/doc/Makefile.am index 5f16fca0..1b992417 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -60,7 +60,8 @@ EXTRA_DIST = \ apibuild.py \ libxml2-api.xml \ xmlcatalog.xml \ - xmllint.xml + xmllint.xml \ + meson.build DOCBOOK_HTML = http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl diff --git a/doc/devhelp/Makefile.am b/doc/devhelp/Makefile.am index d70dc372..9a5c0d03 100644 --- a/doc/devhelp/Makefile.am +++ b/doc/devhelp/Makefile.am @@ -65,7 +65,7 @@ EXTRA_FORMAT= \ up.png \ style.css -EXTRA_DIST = devhelp2.xsl html.xsl +EXTRA_DIST = devhelp2.xsl html.xsl meson.build rebuild: (cd $(srcdir) && $(XSLTPROC) -o libxml2.devhelp2 devhelp2.xsl ../libxml2-api.xml) diff --git a/doc/devhelp/meson.build b/doc/devhelp/meson.build new file mode 100644 index 00000000..398d26e9 --- /dev/null +++ b/doc/devhelp/meson.build @@ -0,0 +1,61 @@ + +html_files = files( + 'general.html', + 'index.html', +) + +html_modules = files( + 'libxml2-HTMLparser.html', + 'libxml2-HTMLtree.html', + 'libxml2-SAX.html', + 'libxml2-SAX2.html', + 'libxml2-c14n.html', + 'libxml2-catalog.html', + 'libxml2-chvalid.html', + 'libxml2-debugXML.html', + 'libxml2-dict.html', + 'libxml2-encoding.html', + 'libxml2-entities.html', + 'libxml2-globals.html', + 'libxml2-hash.html', + 'libxml2-list.html', + 'libxml2-nanoftp.html', + 'libxml2-nanohttp.html', + 'libxml2-parser.html', + 'libxml2-parserInternals.html', + 'libxml2-pattern.html', + 'libxml2-relaxng.html', + 'libxml2-schemasInternals.html', + 'libxml2-schematron.html', + 'libxml2-threads.html', + 'libxml2-tree.html', + 'libxml2-uri.html', + 'libxml2-valid.html', + 'libxml2-xinclude.html', + 'libxml2-xlink.html', + 'libxml2-xmlIO.html', + 'libxml2-xmlautomata.html', + 'libxml2-xmlerror.html', + 'libxml2-xmlexports.html', + 'libxml2-xmlmemory.html', + 'libxml2-xmlmodule.html', + 'libxml2-xmlreader.html', + 'libxml2-xmlregexp.html', + 'libxml2-xmlsave.html', + 'libxml2-xmlschemas.html', + 'libxml2-xmlschemastypes.html', + 'libxml2-xmlstring.html', + 'libxml2-xmlunicode.html', + 'libxml2-xmlversion.html', + 'libxml2-xmlwriter.html', + 'libxml2-xpath.html', + 'libxml2-xpathInternals.html', + 'libxml2-xpointer.html', + 'libxml2.devhelp2', +) + +extra_files = files('home.png', 'left.png', 'right.png', 'style.css', 'up.png') + +devhelp = [files('libxml2.devhelp2'), html_files, html_modules, extra_files] + +install_data(devhelp, install_dir: dir_data / 'gtk-doc' / 'html' / 'libxml2') diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index c14c58d0..3b82da6b 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -28,7 +28,8 @@ EXTRA_DIST = \ index.py \ test1.xml \ test2.xml \ - test3.xml + test3.xml \ + meson.build check_PROGRAMS = \ io1 \ diff --git a/doc/examples/meson.build b/doc/examples/meson.build new file mode 100644 index 00000000..3ce8f520 --- /dev/null +++ b/doc/examples/meson.build @@ -0,0 +1,59 @@ + +## tests + +example_checks = [ + ['io1', ''], + ['io2', ''], + ['parse1', 'test1.xml'], + ['parse2', 'test2.xml'], + ['parse3', ''], + ['parse4', 'test3.xml'], + ['reader1', 'test2.xml'], + ['reader2', 'test2.xml'], + ['reader3', ''], + ['reader4', ['test1.xml', 'test2.xml', 'test3.xml']], + ['testWriter', ''], + ['tree1', 'test2.xml'], + ['tree2', ''], + ['xpath1', ['test3.xml', '//child2']], + ['xpath2', ['test3.xml', '//discarded', 'discarded']], +] + +foreach check : example_checks + exe = executable( + check[0], + files(check[0] + '.c'), + dependencies: xml_dep, + include_directories: config_dir, + ) + test( + check[0], + exe, + args: check[1], + timeout: 0, + workdir: meson.current_source_dir(), + ) +endforeach + +## example files + +example_files = files( + 'index.html', + 'io1.c', + 'io2.c', + 'parse1.c', + 'parse2.c', + 'parse3.c', + 'parse4.c', + 'reader1.c', + 'reader2.c', + 'reader3.c', + 'reader4.c', + 'testWriter.c', + 'tree1.c', + 'tree2.c', + 'xpath1.c', + 'xpath2.c', +) + +install_data(example_files, install_dir: dir_doc / 'examples') diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 00000000..8a2c3462 --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,14 @@ + +install_man(files(['xml2-config.1', 'xmlcatalog.1', 'xmllint.1'])) + + +tutorial_files = files( + 'xmlcatalog.html', + 'xmllint.html', +) + +install_data(tutorial_files, install_dir: dir_doc) + +subdir('devhelp') +subdir('examples') +subdir('tutorial') diff --git a/doc/tutorial/meson.build b/doc/tutorial/meson.build new file mode 100644 index 00000000..96349d2d --- /dev/null +++ b/doc/tutorial/meson.build @@ -0,0 +1,82 @@ + +tutorial_files = files( + 'apa.html', + 'apb.html', + 'apc.html', + 'apd.html', + 'ape.html', + 'apf.html', + 'apg.html', + 'aph.html', + 'api.html', + 'ar01s02.html', + 'ar01s03.html', + 'ar01s04.html', + 'ar01s05.html', + 'ar01s06.html', + 'ar01s07.html', + 'ar01s08.html', + 'ar01s09.html', + 'includeaddattribute.c', + 'includeaddkeyword.c', + 'includeconvert.c', + 'includegetattribute.c', + 'includekeyword.c', + 'includexpath.c', + 'index.html', + 'ix01.html', +) + +install_data(tutorial_files, install_dir: dir_doc / 'tutorial') + +tutorial_image_files = files( + 'images/blank.png', + 'images/caution.png', + 'images/draft.png', + 'images/home.png', + 'images/important.png', + 'images/next.png', + 'images/note.png', + 'images/prev.png', + 'images/tip.png', + 'images/toc-blank.png', + 'images/toc-minus.png', + 'images/toc-plus.png', + 'images/up.png', + 'images/warning.png', +) + +install_data(tutorial_image_files, install_dir: dir_doc / 'tutorial' / 'images') + +tutorial_image_files = files( + 'images/blank.png', + 'images/caution.png', + 'images/draft.png', + 'images/home.png', + 'images/important.png', + 'images/next.png', + 'images/note.png', + 'images/prev.png', + 'images/tip.png', + 'images/toc-blank.png', + 'images/toc-minus.png', + 'images/toc-plus.png', + 'images/up.png', + 'images/warning.png', +) + +install_data(tutorial_image_files, install_dir: dir_doc / 'tutorial' / 'images') +tutorial_image_files = files( + 'images/callouts/1.png', + 'images/callouts/10.png', + 'images/callouts/2.png', + 'images/callouts/3.png', + 'images/callouts/4.png', + 'images/callouts/5.png', + 'images/callouts/6.png', + 'images/callouts/7.png', + 'images/callouts/8.png', + 'images/callouts/9.png', +) + +install_data(tutorial_image_files, install_dir: dir_doc / 'tutorial' / 'images' / 'callouts') diff --git a/example/Makefile.am b/example/Makefile.am index 21130b9a..0f6fb58b 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -4,3 +4,5 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include LDADD = $(top_builddir)/libxml2.la gjobread_SOURCES=gjobread.c + +EXTRA_DIST = meson.build diff --git a/example/meson.build b/example/meson.build new file mode 100644 index 00000000..d95e5aff --- /dev/null +++ b/example/meson.build @@ -0,0 +1,8 @@ + +exe = executable( + 'gjobread', + files('gjobread.c'), + dependencies: xml_dep, + include_directories: config_dir, +) +test('gjobread', exe, timeout: 0) diff --git a/include/Makefile.am b/include/Makefile.am index 2603acc6..328b9932 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in SUBDIRS=libxml private -EXTRA_DIST = win32config.h wsockcompat.h +EXTRA_DIST = win32config.h wsockcompat.h meson.build diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am index 5915e3ec..4451338d 100644 --- a/include/libxml/Makefile.am +++ b/include/libxml/Makefile.am @@ -51,4 +51,4 @@ xmlinc_HEADERS = \ nodist_xmlinc_HEADERS = xmlversion.h -EXTRA_DIST = xmlversion.h.in +EXTRA_DIST = xmlversion.h.in meson.build diff --git a/include/libxml/meson.build b/include/libxml/meson.build new file mode 100644 index 00000000..03b7847d --- /dev/null +++ b/include/libxml/meson.build @@ -0,0 +1,102 @@ + +## xmlversion.h +xmlversion_h = configuration_data() +xmlversion_h.set('VERSION', meson.project_version()) +xmlversion_h.set('LIBXML_VERSION_NUMBER', v_nbr.to_string()) +xmlversion_h.set('LIBXML_VERSION_EXTRA', v_extra) +xmlversion_h.set10('WITH_C14N', want_c14n) +xmlversion_h.set10('WITH_CATALOG', want_catalog) +xmlversion_h.set10('WITH_DEBUG', want_debug) +xmlversion_h.set10('WITH_FTP', want_ftp) +xmlversion_h.set10('WITH_HTML', want_html) +xmlversion_h.set10('WITH_HTTP', want_http) +xmlversion_h.set10('WITH_ICONV', want_iconv) +xmlversion_h.set10('WITH_ICU', want_icu) +xmlversion_h.set10('WITH_ISO8859X', want_iso8859x) +xmlversion_h.set10('WITH_LEGACY', want_legacy) +xmlversion_h.set10('WITH_LZMA', want_lzma) +xmlversion_h.set10('WITH_MODULES', with_modules) +xmlversion_h.set('MODULE_EXTENSION', module_extension) +xmlversion_h.set10('WITH_MEM_DEBUG', want_mem_debug) +xmlversion_h.set10('WITH_OUTPUT', want_output) +xmlversion_h.set10('WITH_PATTERN', want_pattern) +xmlversion_h.set10('WITH_PUSH', want_push) +xmlversion_h.set10('WITH_READER', want_reader) +xmlversion_h.set10('WITH_REGEXPS', want_regexps) +xmlversion_h.set10('WITH_SAX1', want_sax1) +xmlversion_h.set10('WITH_SCHEMAS', want_schemas) +xmlversion_h.set10('WITH_SCHEMATRON', want_schematron) +xmlversion_h.set10('WITH_THREADS', want_threads) +xmlversion_h.set10('WITH_THREAD_ALLOC', want_thread_alloc) +xmlversion_h.set10('WITH_TREE', want_tree) +xmlversion_h.set10('WITH_VALID', want_valid) +xmlversion_h.set10('WITH_WRITER', want_writer) +xmlversion_h.set10('WITH_XINCLUDE', want_xinclude) +xmlversion_h.set10('WITH_XPATH', want_xpath) +xmlversion_h.set10('WITH_XPTR', want_xptr) +xmlversion_h.set10('WITH_XPTR_LOCS', want_xptr_locs) +xmlversion_h.set10('WITH_ZLIB', want_zlib) + +configure_file( + input: 'xmlversion.h.in', + output: 'xmlversion.h', + configuration: xmlversion_h, + install_dir: dir_pkginclude + '/libxml', +) + +#vcs_tag( +# command : [ 'git', 'describe', '2>/dev/null' ], +# input : 'xmlversion.h.in', +# output : 'xmlversion.h', +# replace_string : 'LIBXML_VERSION_EXTRA' +#) + +libxml_headers = files( + 'HTMLparser.h', + 'HTMLtree.h', + 'SAX.h', + 'SAX2.h', + 'c14n.h', + 'catalog.h', + 'chvalid.h', + 'debugXML.h', + 'dict.h', + 'encoding.h', + 'entities.h', + 'globals.h', + 'hash.h', + 'list.h', + 'nanoftp.h', + 'nanohttp.h', + 'parser.h', + 'parserInternals.h', + 'pattern.h', + 'relaxng.h', + 'schemasInternals.h', + 'schematron.h', + 'threads.h', + 'tree.h', + 'uri.h', + 'valid.h', + 'xinclude.h', + 'xlink.h', + 'xmlIO.h', + 'xmlautomata.h', + 'xmlerror.h', + 'xmlexports.h', + 'xmlmemory.h', + 'xmlmodule.h', + 'xmlreader.h', + 'xmlregexp.h', + 'xmlsave.h', + 'xmlschemas.h', + 'xmlschemastypes.h', + 'xmlstring.h', + 'xmlunicode.h', + 'xmlwriter.h', + 'xpath.h', + 'xpathInternals.h', + 'xpointer.h', +) + +install_headers(libxml_headers, install_dir: dir_pkginclude / 'libxml') diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 00000000..f99f9bec --- /dev/null +++ b/include/meson.build @@ -0,0 +1,2 @@ + +inc_dir = include_directories('.') diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..f72de1ae --- /dev/null +++ b/meson.build @@ -0,0 +1,875 @@ +project( + 'libxml2', + 'c', + version: '2.13.0', + license: 'MIT', + default_options: ['buildtype=debug', 'warning_level=3'], + meson_version: '>= 0.61', +) + +v_array = meson.project_version().split('.') +v_maj = v_array[0] +v_min = v_array[1] +v_mic = v_array[2] +v_nbr = v_maj.to_int() * 10000 + v_min.to_int() * 100 + v_mic.to_int() +v_extra = '' +r = run_command('git', 'describe', check: false) +if (r.returncode() == 0) + v_extra = '-GIT' + r.stdout().strip() +endif + +# install paths +dir_prefix = get_option('prefix') +dir_bin = dir_prefix / get_option('bindir') +dir_include = dir_prefix / get_option('includedir') +dir_pkginclude = dir_include / meson.project_name() +dir_lib = dir_prefix / get_option('libdir') +dir_data = dir_prefix / get_option('datadir') +dir_doc = dir_data / 'doc' / 'libxml2' +dir_locale = dir_prefix / get_option('localedir') + +# host + +host_os = host_machine.system() + +cygwin = 'cygwin' +windows = 'windows' +sys_cygwin = cygwin.contains(host_os) +sys_windows = windows.contains(host_os) + +libxml2_cflags = [] +xml_cflags = '' + +if sys_cygwin or sys_windows + if get_option('default_library') == 'static' + xml_cflags = '-DLIBXML_STATIC' + libxml2_cflags += '-DLIBXML_STATIC' + endif +endif + +# binaries +cc = meson.get_compiler('c') + +cc.has_type('uint32_t', prefix: '#include ') + +# options +want_c14n = get_option('c14n') +want_catalog = get_option('catalog') +want_debug = get_option('debuging') +want_fexceptions = get_option('fexceptions') +want_ftp = get_option('ftp') +want_history = get_option('history') +want_html = get_option('html') +want_http = get_option('http') +want_iconv = get_option('iconv') +want_icu = get_option('icu') +want_ipv6 = get_option('ipv6') +want_iso8859x = get_option('iso8859x') +want_legacy = get_option('legacy') +want_lzma = get_option('lzma') +want_mem_debug = get_option('mem-debug') +want_modules = get_option('modules') +want_output = get_option('output') +want_pattern = get_option('pattern') +want_push = get_option('push') +want_python = get_option('python') +want_reader = get_option('reader') +want_readline = get_option('readline') +want_regexps = get_option('regexps') +want_run_debug = get_option('run-debug') +want_sax1 = get_option('sax1') +want_schemas = get_option('schemas') +want_schematron = get_option('schematron') +want_threads = get_option('threads') +want_thread_alloc = get_option('thread-alloc') +want_tls = get_option('tls') +want_tree = get_option('tree') +want_valid = get_option('valid') +want_writer = get_option('writer') +want_xinclude = get_option('xinclude') +want_xpath = get_option('xpath') +want_xptr = get_option('xptr') +want_xptr_locs = get_option('xptr-locs') +want_zlib = get_option('zlib') + +# hard dependencies on options + +if want_c14n == true + if want_output == false + message('-Dc14n=true overrides -Doutput') + endif + want_output = true + if want_xpath == false + message('-Dc14n=true overrides -Dxpath') + endif + want_xpath = true +endif + +if want_schemas == true + if want_pattern == false + message('-Dschemas=true overrides -Dpattern') + endif + want_pattern = true + if want_regexps == false + message('-Dschemas=true overrides -Dregexps') + endif + want_regexps = true +endif + +if want_schematron == true + if want_pattern == false + message('-Dschematron=true overrides -Dpattern') + endif + want_pattern = true + if want_tree == false + message('-Dschematron=true overrides -Dtree') + endif + want_tree = true + if want_xpath == false + message('-Dschematron=true overrides -Dxpath') + endif + want_xpath = true +endif + +if want_reader == true + if want_push == false + message('-Dreader=true overrides -Dpush') + endif + want_push = true + if want_tree == false + message('-Dreader=true overrides -Dtree') + endif + want_tree = true +endif + +if want_writer == true + if want_output == false + message('-Dwriter=true overrides -Doutput') + endif + want_output = true + if want_push == false + message('-Dwriter=true overrides -Dpush') + endif + want_push = true +endif + +if want_xinclude == true + if want_xpath == false + message('-Dxinclude=true overrides -Dxpath') + endif + want_xpath = true +endif + +if want_xptr_locs == true + if want_xptr == false + message('-Dxptr-locs=true overrides -Dxptr') + endif + want_xptr = true +endif + +if want_xptr == true + if want_xpath == false + message('-Dxptr=true overrides -Dxpath') + endif + want_xpath = true +endif + +# minimum dependencies + +if get_option('minimum') + want_c14n = false + want_catalog = false + want_debug = false + want_fexceptions = false + want_history = false + want_html = false + want_http = false + want_iconv = false + want_ipv6 = false + want_iso8859x = false + want_lzma = false + want_mem_debug = false + want_modules = false + want_output = false + want_pattern = false + want_push = false + want_python = false + want_reader = false + want_readline = false + want_regexps = false + want_run_debug = false + want_sax1 = false + want_schemas = false + want_schematron = false + want_threads = false + want_thread_alloc = false + want_tree = false + want_valid = false + want_writer = false + want_xinclude = false + want_xpath = false + want_xptr = false + want_xptr_locs = false + want_zlib = false +else + # Disable dependent modules + if want_output == false + want_c14n = false + want_writer = false + endif + if want_pattern == false + want_schemas = false + want_schematron = false + endif + if want_push == false + want_reader = false + want_writer = false + endif + if want_regexps == false + want_schemas = false + endif + if want_tree == false + want_reader = false + want_schematron = false + endif + if want_xpath == false + want_c14n = false + want_schematron = false + want_xinclude = false + want_xptr = false + endif +endif + +cflags_try = [] + +### workaround for native compilers, see configure.ac +if cc.get_argument_syntax() == 'gcc' + cflags_try += [ + '-Wshadow', + '-Wpointer-arith', + '-Wcast-align', + '-Wwrite-strings', + '-Wstrict-prototypes', + '-Wmissing-prototypes', + '-Wno-long-long', + '-Wno-format-extra-args', + ] + + if want_fexceptions == true + cflags_try += '-fexceptions' + endif + + if host_machine.cpu_family() == 'alpha' + cflags_try += '-mieee' + endif +else + if host_machine.cpu_family() == 'alpha' + cflags_try += '-ieee' + elif host_machine.cpu_family() == 'parisc' + cflags_try += '-Wp,-H30000' + endif +endif + +foreach cf : cflags_try + if cc.has_argument(cf) + libxml2_cflags += cf + endif +endforeach + +# configuration +# +# X : done +# N : not done +# +# [X] config.h.in +# [X] include/libxml/xmlversion.h.in +# [N] libxml-2.0-uninstalled.pc.in +# [X] libxml-2.0.pc.in +# [X] libxml2-config.cmake.in +# [X] python/setup.py.in +# [N] xml2-config.in + +## config.h +config_h = configuration_data() +config_h.set_quoted('PACKAGE_NAME', meson.project_name()) +config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) +config_h.set_quoted('PACKAGE_BIN_DIR', dir_bin) +config_h.set_quoted('PACKAGE_LIB_DIR', dir_lib) +config_h.set_quoted('PACKAGE_DATA_DIR', dir_data) +config_h.set_quoted('LOCALEDIR', dir_locale) + +# header files +xml_check_headers = [ + 'stdint.h', + 'inttypes.h', + 'fcntl.h', + 'unistd.h', + 'sys/stat.h', + 'sys/mman.h', + 'sys/socket.h', + 'netinet/in.h', + 'arpa/inet.h', + 'netdb.h', + 'sys/select.h', + 'poll.h', + 'sys/time.h', + 'sys/timeb.h', + 'dl.h', + 'dlfcn.h', + 'glob.h', +] + +foreach header : xml_check_headers + if cc.has_header(header) + config_h.set10('HAVE_' + header.underscorify().to_upper(), true) + endif +endforeach + +# library functions +xml_check_functions = [ + # fct | header + ['gettimeofday', 'sys/time.h'], + ['ftime', 'sys/timeb.h'], + ['stat', 'sys/stat.h'], + ['isascii', 'ctype.h'], + ['mmap', 'sys/mman.h'], + ['munmap', 'sys/mman.h'], +] + +foreach function : xml_check_functions + if cc.has_header_symbol(function[1], function[0]) + config_h.set10('HAVE_' + function[0].to_upper(), true) + endif +endforeach + +# library + +config_dir = [include_directories('.'), include_directories('include')] + +## dependencies + +xml_deps = [] + +### math library +if sys_windows == false + m_dep = cc.find_library('m', required: false) + if m_dep.found() + xml_deps += m_dep + endif +endif + +### thread local storage +support_tls = true +if want_tls == true + tls_src = ''' +#include +int main() +{ + _Thread_local int v; + return 0; +} + ''' + res = cc.compiles(tls_src, name: '_Thread_local') + if res == true + config_h.set('XML_THREAD_LOCAL', '_Thread_local') + else + tls_src = ''' +int main() +{ + __thread int v; + return 0; +} + ''' + res = cc.compiles(tls_src, name: '__thread') + if res == true + config_h.set('XML_THREAD_LOCAL', '__thread') + else + tls_src = ''' +int main() +{ + __declspec(thread) int v; + return 0; +} + ''' + res = cc.compiles(tls_src, name: '__declspec(thread)') + if res == true + config_h.set('XML_THREAD_LOCAL', '__declspec(thread)') + else + want_tls = false + support_tls = false + endif + endif + endif +endif + +### __attribute__((destructor)) +if cc.has_function_attribute('destructor') + config_h.set10('HAVE_ATTRIBUTE_DESTRUCTOR', true) + config_h.set('ATTRIBUTE_DESTRUCTOR', '__attribute__((destructor))') +endif + +### DSO support +with_modules = false +if want_modules == true + if sys_cygwin == true + module_extension = '.dll' + elif sys_windows == true + module_extension = '.dll' + with_modules = true + else + module_extension = '.so' + endif + + if with_modules == false + dl_dep = dependency('dl', required: false) + if dl_dep.found() + config_h.set10('HAVE_DLOPEN', true) + xml_deps += dl_dep + with_modules = true + endif + endif +endif + +### threads +if want_threads == true + if sys_windows == false + threads_dep = dependency('threads') + if threads_dep.found() + config_h.set10('HAVE_PTHREAD_H', true) + xml_deps += threads_dep + else + want_threads = false + endif + endif +endif + +if want_threads == true + thread_cflags = '-D_REENTRANT' + libxml2_cflags += thread_cflags +endif + +want_thread_alloc = ( + (want_threads == true and want_threads == true) ? true : false +) + +### xmllint shell history +xmllint_deps = [] +if want_history == true and want_readline == true + termlib_lib = ['ncurses', 'curses', 'termcap', 'terminfo', 'termlib'] + + foreach tl : termlib_lib + termlib_dep = cc.find_library(tl) + if ( + termlib_dep.found() + and cc.has_function('tputs', dependencies: termlib_dep) + ) + xmllint_deps += termlib_dep + config_h.set10('HAVE_LIB' + tl.underscorify().to_upper(), true) + break + endif + endforeach + + history_dep = dependency('history', required: false) + if history_dep.found() + xmllint_deps += history_dep + config_h.set10('HAVE_LIBHISTORY', true) + endif + + readline_dep = dependency('readline', required: false) + if readline_dep.found() + xmllint_deps += readline_dep + config_h.set10('HAVE_LIBREADLINE', true) + endif +endif + +### crypto +if sys_windows == true + bcrypt_dep = cc.find_library('bcrypt', required: true) + xml_deps += bcrypt_dep +endif + +### inet +if want_http == true or want_ftp == true + if sys_windows == true + ws2_dep = cc.find_library('ws2_32', required: true) + xml_deps += ws2_dep + else + has_in_libc = cc.has_function('gethostbyname') + if has_in_libc == false + nsl_dep = cc.find_library('nsl', required: true) + if nsl_dep.found() + has_in_nsl = cc.has_function( + 'gethostbyname', + dependencies: nsl_dep, + required: false, + ) + if has_in_nsl == true + xml_deps += nsl_dep + endif + endif + endif + endif + + ### socket length + socklen_src = ''' +#include +#ifdef _WIN32 + #include +#else + #include +#endif +int main() +{ + (void)getsockopt (1, 1, 1, NULL, (socklen_t *)NULL); + return 0; +} + ''' + res = cc.compiles(socklen_src, name: 'socket length as socklen_t') + if res == true + config_h.set('XML_SOCKLEN_T', 'socklen_t') + else + socklen_src = ''' +#include +#include +int main() +{ + (void)getsockopt (1, 1, 1, NULL, (size_t *)NULL); + return 0; +} + ''' + res = cc.compiles(socklen_src, name: 'socket length as size_t') + if res == true + config_h.set('XML_SOCKLEN_T', 'size_t') + else + socklen_src = ''' +#include +#include +int main() +{ + (void)getsockopt (1, 1, 1, NULL, (int *)NULL); + return 0; +} + ''' + res = cc.compiles(socklen_src, name: 'socket length as int') + if res == false + message('could not determine socket length type, use int') + endif + config_h.set('XML_SOCKLEN_T', 'int') + endif + endif + + if want_ipv6 == true + ### IPV6 on Windows has been supported since Windows XP SP1 (around 2003) + ### see: + ### https://learn.microsoft.com/en-us/windows/win32/winsock/ipv6-support-2 + ### nevertheless, we check it like autotools + ipv6_src = ''' +#ifdef _WIN32 +#include +#else +#include +#ifdef HAVE_NETDB_H +#include +#endif +#endif +int main() +{ + struct sockaddr_storage ss; + socket(AF_INET6, SOCK_STREAM, 0); + getaddrinfo(0, 0, 0, 0); + return 0; +} + ''' + res = cc.compiles(ipv6_src, name: 'support for IPV6') + if res == true + config_h.set10('SUPPORT_IP6', true) + endif + endif +endif + +### zlib +if want_zlib == true + zlib_dep = dependency('zlib', required: false) + if zlib_dep.found() + xml_deps += zlib_dep + else + want_zlib = false + endif +endif + +### lzma +if want_lzma == true + lzma_dep = dependency('liblzma', required: false) + if lzma_dep.found() + xml_deps += lzma_dep + else + want_lzma = false + endif +endif + +### iconv +if want_iconv == true + iconv_dep = dependency('iconv', required: false) + if iconv_dep.found() + xml_deps += iconv_dep + else + want_iconv = false + endif +endif + +if want_iconv == false and want_iso8859x == false + want_iso8859x = false +else + want_iso8859x = true +endif + +# icu +if want_icu == true + icu_dep = dependency('icu-i18n', method: 'pkg-config', required: false) + if icu_dep.found() + def_var = icu_dep.get_variable(pkgconfig: 'DEFS') + config_dir += include_directories(def_var) + xml_deps += icu_dep + else + want_icu = false + endif +endif + +subdir('include/libxml') + +# Set config_h after all subdirs and dependencies have set values + +configure_file(output: 'config.h', configuration: config_h) + +## libxml2 library + +xml_src = [ + 'buf.c', + 'chvalid.c', + 'dict.c', + 'entities.c', + 'encoding.c', + 'error.c', + 'globals.c', + 'hash.c', + 'list.c', + 'parser.c', + 'parserInternals.c', + 'SAX2.c', + 'threads.c', + 'tree.c', + 'uri.c', + 'valid.c', + 'xmlIO.c', + 'xmlmemory.c', + 'xmlstring.c', +] + +xml_opt_src = [ + [want_c14n, ['c14n.c']], + [want_catalog, ['catalog.c']], + [want_debug, ['debugXML.c']], + [want_ftp, ['nanoftp.c']], + [want_html, ['HTMLparser.c', 'HTMLtree.c']], + [want_http, ['nanohttp.c']], + [want_legacy, ['legacy.c']], + [want_lzma, ['xzlib.c']], + [with_modules, ['xmlmodule.c']], + [want_output, ['xmlsave.c']], + [want_pattern, ['pattern.c']], + [want_reader, ['xmlreader.c']], + [want_regexps, ['xmlregexp.c', 'xmlunicode.c']], + [want_sax1, ['SAX.c']], + [want_schemas, ['relaxng.c', 'xmlschemas.c', 'xmlschemastypes.c']], + [want_schemas and not want_xpath, ['xpath.c']], + [want_schematron, ['schematron.c']], + [want_writer, ['xmlwriter.c']], + [want_xinclude, ['xinclude.c']], + [want_xpath, ['xpath.c']], + [want_xptr, ['xlink.c', 'xpointer.c']], +] + +foreach file : xml_opt_src + want = file[0] + src = file[1] + if want == true + if src.length() > 1 + foreach s : src + xml_src += s + endforeach + else + xml_src += src + endif + endif +endforeach + +xml_lib = library( + 'xml2', + files(xml_src), + c_args: libxml2_cflags, + dependencies: xml_deps, + include_directories: config_dir, + install: true, + version: meson.project_version(), +) + +xml_dep = declare_dependency(link_with: xml_lib) + +## xmllint tool + +executable( + 'xmllint', + files('xmllint.c'), + dependencies: [xml_dep, xmllint_deps], + include_directories: config_dir, + install: true, +) + +## xmlcatalog tool + +executable( + 'xmlcatalog', + files('xmlcatalog.c'), + dependencies: [xml_dep, xmllint_deps], + include_directories: config_dir, + install: true, +) + +## testdso module + +testdso_mod = shared_module( + 'testdso', + files('testdso.c'), + build_rpath: get_option('libdir'), + include_directories: config_dir, + name_prefix: '', +) + +## tests + +checks = [ + 'runsuite', + 'runtest', + 'runxmlconf', +# Disabled for now, see #694 +# 'testModule', + 'testThreads', + 'testapi', + 'testchar', + 'testdict', + 'testlimits', + 'testparser', + 'testrecurse', +] + +foreach check : checks + exe = executable( + check, + files(check + '.c'), + dependencies: xml_dep, + include_directories: config_dir, + ) + if check != 'testlimits' + test(check, exe, timeout: 0, workdir: meson.current_source_dir()) + endif +endforeach + +subdir('example') +subdir('doc') + +if want_python == true + subdir('python') +endif + +## pc files + +pkgmod = import('pkgconfig') + +pkgmod.generate( + xml_lib, + description: 'libXML library version2.', + filebase: 'libxml-2.0', + name: 'libXML', + variables: 'modules=' + with_modules.to_string('1', '0'), +) + +## libxml2-config.cmake file + +config_cmake = configuration_data() +config_cmake.set('LIBXML_MAJOR_VERSION', v_maj) +config_cmake.set('LIBXML_MINOR_VERSION', v_min) +config_cmake.set('LIBXML_MICRO_VERSION', v_mic) +config_cmake.set('VERSION', meson.project_version()) +config_cmake.set('WITH_ICONV', want_iconv.to_int().to_string()) +config_cmake.set('WITH_ICU', want_icu.to_int().to_string()) +config_cmake.set('WITH_LZMA', want_lzma.to_int().to_string()) +config_cmake.set('WITH_MODULES', want_modules.to_int().to_string()) +config_cmake.set('WITH_THREADS', want_threads.to_int().to_string()) +config_cmake.set('WITH_ZLIB', want_zlib.to_int().to_string()) +config_cmake.set('XML_CFLAGS', xml_cflags) +configure_file( + input: 'libxml2-config.cmake.in', + output: 'libxml2-config.cmake', + configuration: config_cmake, + install_dir: dir_lib / 'cmake' / 'libxml2', +) + +install_data(files('libxml.m4'), install_dir: dir_data / 'aclocal') + +install_data(files('xmllint.c'), install_dir: dir_doc / 'examples') + +if support_tls == false + message('===============================================================') + message('WARNING: Your C compiler appears to not support thread-local') + message('storage. Future versions of libxml2 will require this feature') + message('for multi-threading.') + message('===============================================================\n', + ) +endif + +# summary + +summary( + { + 'OS': host_os, + 'c14n': want_c14n, + 'catalog': want_catalog, + 'debug': want_debug, + 'fexceptions': want_fexceptions, + 'ftp': want_ftp, + 'history': want_history, + 'html': want_html, + 'http': want_http, + 'iconv': want_iconv, + 'icu': want_icu, + 'ipv6': want_ipv6, + 'iso8859x': want_iso8859x, + 'legacy': want_legacy, + 'lzma': want_lzma, + 'mem-debug': want_mem_debug, + 'modules': want_modules, + 'output': want_output, + 'pattern': want_pattern, + 'push': want_push, + 'python': want_python, + 'reader': want_reader, + 'readline': want_readline, + 'regexps': want_regexps, + 'run-debug': want_run_debug, + 'sax1': want_sax1, + 'schemas': want_schemas, + 'schematron': want_schematron, + 'threads': want_threads, + 'thread-alloc': want_thread_alloc, + 'tls': want_tls, + 'tree': want_tree, + 'valid': want_valid, + 'writer': want_writer, + 'xinclude': want_xinclude, + 'xpath': want_xpath, + 'xptr': want_xptr, + 'xptr-locs': want_xptr_locs, + 'zlib': want_zlib, + }, + section: 'Configuration Options Summary:', +) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..ea66b306 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,280 @@ + +# AC_ARG_WITH / AC_ARG_ENABLE in configure.ac +# [X] c14n +# [X] catalog +# [M] coverage - use meson, not minimum +# [X] debugging +# [X] fexceptions +# [X] ftp - not minimum +# [X] history +# [X] html +# [X] http +# [X] iconv +# [X] icu - not minimum +# [X] ipv6 +# [X] iso8859x +# [X] legacy +# [X] lzma +# [X] mem-debug +# [X] modules +# [X] output +# [X] pattern +# [X] push +# [ ] python +# [X] reader +# [X] readline +# [X] regexps +# [ ] run-debug - not used +# [X] sax1 +# [X] schemas +# [X] schematron +# [X] threads +# [X] thread-alloc +# [X] tls +# [X] tree +# [X] valid +# [X] writer +# [X] xinclude +# [X] xpath +# [X] xptr +# [X] xptr-locs +# [X] zlib + +# [X] minimum +# [X] ipv6 + + +option('c14n', + type: 'boolean', + value: true, + description: 'Canonical XML 1.0 support' +) + +option('catalog', + type: 'boolean', + value: true, + description: 'XML Catalogs support' +) + +option('debuging', + type: 'boolean', + value: true, + description: 'Debugging module and shell' +) + +option('fexceptions', + type: 'boolean', + value: false, + description: 'add GCC flag -fexceptions for C++ exceptions' +) + +option('ftp', + type: 'boolean', + value: false, + description: 'FTP support' +) + +option('history', + type: 'boolean', + value: false, + description: 'History support for shell' +) + +option('html', + type: 'boolean', + value: true, + description: 'HTML parser' +) + +option('http', + type: 'boolean', + value: true, + description: 'HTTP support' +) + +# TODO meson custom dependency +option('iconv', + type: 'boolean', + value: true, + description: 'iconv support' +) + +option('icu', + type: 'boolean', + value: false, + description: 'ICU support' +) + +option('ipv6', + type: 'boolean', + value: true, + description: 'Compilation of IPv6 code' +) + +option('iso8859x', + type: 'boolean', + value: true, + description: 'ISO-8859-X support if no iconv' +) + +option('legacy', + type: 'boolean', + value: false, + description: 'Maximum ABI compatibility' +) + +option('lzma', + type: 'boolean', + value: false, + description: 'LZMA support' +) + +option('mem-debug', + type: 'boolean', + value: false, + description: 'Memory debugging module' +) + +option('modules', + type: 'boolean', + value: true, + description: 'Dynamic modules support' +) + +option('output', + type: 'boolean', + value: true, + description: 'Serialization support' +) + +option('pattern', + type: 'boolean', + value: true, + description: 'xmlPattern selection interface' +) + +option('push', + type: 'boolean', + value: true, + description: 'push parser interfaces' +) + +option('python', + type: 'boolean', + value: true, + description: 'Python bindings' +) + +option('reader', + type: 'boolean', + value: true, + description: 'xmlReader parsing interface' +) + +option('readline', + type: 'boolean', + value: true, + description: 'use readline in DIR (for shell history)' +) + +option('regexps', + type: 'boolean', + value: true, + description: 'Regular expressions support' +) + +option('run-debug', + type: 'boolean', + value: false, + description: 'Runtime debugging module' +) + +option('sax1', + type: 'boolean', + value: true, + description: 'Older SAX1 interface' +) + +option('schemas', + type: 'boolean', + value: true, + description: 'XML Schemas 1.0 and RELAX NG support' +) + +option('schematron', + type: 'boolean', + value: true, + description: 'Schematron support' +) + +option('threads', + type: 'boolean', + value: true, + description: 'Multithreading support' +) + +option('thread-alloc', + type: 'boolean', + value: false, + description: 'per-thread malloc hooks' +) + +option('tls', + type: 'boolean', + value: false, + description: 'thread-local storage' +) + +option('tree', + type: 'boolean', + value: true, + description: 'DOM like tree manipulation APIs' +) + +option('valid', + type: 'boolean', + value: true, + description: 'DTD validation support' +) + +option('writer', + type: 'boolean', + value: true, + description: 'xmlWriter serialization interface' +) + +option('xinclude', + type: 'boolean', + value: true, + description: 'XInclude 1.0 support' +) + +option('xpath', + type: 'boolean', + value: true, + description: 'XPath 1.0 support' +) + +option('xptr', + type: 'boolean', + value: true, + description: 'XPointer support' +) + +option('xptr-locs', + type: 'boolean', + value: false, + description: 'XPointer ranges and points' +) + +option('zlib', + type: 'boolean', + value: false, + description: 'ZLIB support' +) + +option('minimum', + type: 'boolean', + value: false, + description: 'build a minimally sized library (default=false)' +) diff --git a/python/Makefile.am b/python/Makefile.am index 05d167b6..c9f3efad 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -10,7 +10,8 @@ EXTRA_DIST = \ generator.py \ libxml.py \ libxml2-python-api.xml \ - pyproject.toml + pyproject.toml \ + meson.build if WITH_PYTHON AM_CPPFLAGS = \ diff --git a/python/meson.build b/python/meson.build new file mode 100644 index 00000000..d5a39fd3 --- /dev/null +++ b/python/meson.build @@ -0,0 +1,36 @@ + +pymod = import('python') +py = pymod.find_installation('python3', required: false) + +if py.found() == true + r = run_command(py, 'generator.py', meson.current_source_dir(), check: true) + + libxml2mod_src = ['libxml.c', 'libxml2-py.c', 'types.c'] + + message(py.get_install_dir()) + + py.extension_module( + 'libxml2mod', + files(libxml2mod_src), + dependencies: [py.dependency(), xml_dep], + include_directories: [config_dir], + install: true, + ) + + setup_py = configuration_data() + setup_py.set('prefix', get_option('prefix')) + setup_py.set('LIBXML_VERSION', meson.project_version()) + setup_py.set('WITH_ICONV', want_iconv.to_int()) + setup_py.set('WITH_ICU', want_icu.to_int()) + setup_py.set('WITH_LZMA', want_lzma.to_int()) + setup_py.set('WITH_ZLIB', want_zlib.to_int()) + setup_py.set('WITH_THREADS', want_threads.to_int()) + configure_file( + input: 'setup.py.in', + output: 'setup.py', + configuration: setup_py, + ) + + subdir('tests') + +endif diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index 588dcddc..e30058e3 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -75,3 +75,5 @@ check-local: fi ; \ done) endif + +EXTRA_DIST = meson.build diff --git a/python/tests/meson.build b/python/tests/meson.build new file mode 100644 index 00000000..9027c45b --- /dev/null +++ b/python/tests/meson.build @@ -0,0 +1,63 @@ + +python_test_files = files( + 'attribs.py', + 'build.py', + 'compareNodes.py', + 'ctxterror.py', + 'cutnpaste.py', + 'dtdvalid.py', + 'error.py', + 'inbuf.py', + 'indexes.py', + 'input_callback.py', + 'nsdel.py', + 'outbuf.py', + 'push.py', + 'pushSAX.py', + 'pushSAXhtml.py', + 'reader.py', + 'reader2.py', + 'reader3.py', + 'reader4.py', + 'reader5.py', + 'reader6.py', + 'reader7.py', + 'reader8.py', + 'readererr.py', + 'readernext.py', + 'regexp.py', + 'relaxng.py', + 'resolver.py', + 'schema.py', + 'serialize.py', + 'setup_test.py', + 'sync.py', + 'thread2.py', + 'tst.py', + 'tstLastError.py', + 'tstURI.py', + 'tstmem.py', + 'tstxpath.py', + 'validDTD.py', + 'validRNG.py', + 'validSchemas.py', + 'validate.py', + 'walker.py', + 'xpath.py', + 'xpathext.py', + 'xpathleak.py', + 'xpathns.py', + 'xpathret.py', +) + +xml_files = files( + 'invalid.xml', + 'test.dtd', + 'tst.xml', + 'valid.xml', +) + +install_data( + [python_test_files, xml_files, files('setup_test.py')], + install_dir: dir_doc / 'python' / 'examples', +)