• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1project(
2    'libxml2',
3    'c',
4    version: files('VERSION'),
5    license: 'MIT',
6    default_options: [
7        'c_std=c11,c99,c89',
8        'buildtype=debug',
9        'warning_level=3',
10    ],
11    meson_version: '>= 0.61',
12)
13
14v_array = meson.project_version().split('.')
15v_maj = v_array[0].to_int()
16v_min = v_array[1].to_int()
17v_mic = v_array[2].to_int()
18v_nbr = v_maj * 10000 + v_min * 100 + v_mic
19v_extra = ''
20r = run_command('git', 'describe', check: false)
21if (r.returncode() == 0)
22    v_extra = '-GIT' + r.stdout().strip()
23endif
24
25# install paths
26dir_prefix = get_option('prefix')
27dir_bin = dir_prefix / get_option('bindir')
28dir_include = dir_prefix / get_option('includedir')
29dir_pkginclude = dir_include / meson.project_name()
30dir_lib = dir_prefix / get_option('libdir')
31dir_data = dir_prefix / get_option('datadir')
32dir_doc = dir_data / 'doc' / 'libxml2'
33dir_locale = dir_prefix / get_option('localedir')
34
35# host
36
37host_os = host_machine.system()
38
39cygwin = 'cygwin'
40windows = 'windows'
41sys_cygwin = cygwin.contains(host_os)
42sys_windows = windows.contains(host_os)
43
44libxml2_cflags = []
45xml_cflags = ''
46dep_args = []
47
48if sys_cygwin or sys_windows
49    if get_option('default_library') == 'static'
50        xml_cflags = '-DLIBXML_STATIC'
51        libxml2_cflags += '-DLIBXML_STATIC'
52        dep_args += '-DLIBXML_STATIC'
53    endif
54endif
55
56# binaries
57cc = meson.get_compiler('c')
58
59# global compiler flags
60
61global_args = [
62    '-D_XOPEN_SOURCE=600',
63
64    # Enabled by warning_level=3
65    # '-pedantic',
66    # '-Wall',
67    # '-Wextra',
68
69    '-Wshadow',
70    '-Wpointer-arith',
71    '-Wcast-align',
72    '-Wwrite-strings',
73    '-Wstrict-prototypes',
74    '-Wmissing-prototypes',
75    '-Wno-long-long',
76    '-Wno-format-extra-args',
77    '-Wno-array-bounds',
78]
79global_args = cc.get_supported_arguments(global_args)
80add_project_arguments(global_args, language: 'c')
81
82# options
83
84# disabled by default
85want_icu = get_option('icu').enabled()
86want_legacy = get_option('legacy').enabled()
87want_thread_alloc = get_option('thread-alloc').enabled()
88want_tls = get_option('tls').enabled()
89
90# default depends on minimum option
91
92want_minimum = get_option('minimum')
93
94feature = get_option('catalog')
95want_catalog = want_minimum ? feature.enabled() : feature.allowed()
96
97feature = get_option('debugging')
98want_debug = want_minimum ? feature.enabled() : feature.allowed()
99
100feature = get_option('html')
101want_html = want_minimum ? feature.enabled() : feature.allowed()
102
103feature = get_option('iconv')
104want_iconv = want_minimum ? feature.enabled() : feature.allowed()
105
106feature = get_option('iso8859x')
107want_iso8859x = want_minimum ? feature.enabled() : feature.allowed()
108
109feature = get_option('python')
110want_python = want_minimum ? feature.enabled() : feature.allowed()
111
112feature = get_option('modules')
113want_modules = want_minimum ? feature.enabled() : feature.allowed()
114
115feature = get_option('sax1')
116want_sax1 = want_minimum ? feature.enabled() : feature.allowed()
117
118feature = get_option('threads')
119want_threads = want_minimum ? feature.enabled() : feature.allowed()
120
121feature = get_option('valid')
122want_valid = want_minimum ? feature.enabled() : feature.allowed()
123
124feature = get_option('xinclude')
125want_xinclude = want_minimum ? feature.enabled() : feature.allowed()
126
127# default depends on legacy option
128
129feature = get_option('http')
130want_http = want_legacy ? feature.allowed() : feature.enabled()
131
132feature = get_option('lzma')
133want_lzma = want_legacy ? feature.allowed() : feature.enabled()
134
135feature = get_option('zlib')
136want_zlib = want_legacy ? feature.allowed() : feature.enabled()
137
138# dependencies
139
140feature = get_option('output')
141want_output = not want_minimum \
142    or get_option('c14n').enabled() \
143    or get_option('writer').enabled() ? \
144    feature.allowed() : feature.enabled()
145
146feature = get_option('pattern')
147want_pattern = not want_minimum \
148    or get_option('schemas').enabled() \
149    or get_option('schematron').enabled() ? \
150    feature.allowed() : feature.enabled()
151
152feature = get_option('regexps')
153want_regexps = not want_minimum \
154    or get_option('schemas').enabled() ? \
155    feature.allowed() : feature.enabled()
156
157feature = get_option('push')
158want_push = not want_minimum \
159    or get_option('reader').enabled() \
160    or get_option('writer').enabled() ? \
161    feature.allowed() : feature.enabled()
162
163feature = get_option('readline')
164want_readline = get_option('history').enabled() ? \
165    feature.allowed() : feature.enabled()
166
167feature = get_option('xpath')
168want_xpath = not want_minimum \
169    or get_option('c14n').enabled() \
170    or get_option('schematron').enabled() \
171    or get_option('xptr').enabled() ? \
172    feature.allowed() : feature.enabled()
173
174feature = get_option('c14n') \
175    .require(want_output, error_message: 'c14n requires output') \
176    .require(want_xpath, error_message: 'c14n requires xpath')
177want_c14n = want_minimum ? feature.enabled() : feature.allowed()
178
179feature = get_option('history') \
180    .require(want_readline, error_message: 'history requires readline')
181want_history = feature.enabled()
182
183feature = get_option('reader') \
184    .require(want_push, error_message: 'reader requires push')
185want_reader = want_minimum ? feature.enabled() : feature.allowed()
186
187feature = get_option('schemas') \
188    .require(want_pattern, error_message: 'schemas requires pattern') \
189    .require(want_regexps, error_message: 'schemas requires regexps')
190want_schemas = want_minimum ? feature.enabled() : feature.allowed()
191
192feature = get_option('schematron') \
193    .require(want_pattern, error_message: 'schematron requires pattern') \
194    .require(want_xpath, error_message: 'schematron requires xpath')
195want_schematron = want_minimum ? feature.enabled() : feature.allowed()
196
197feature = get_option('writer') \
198    .require(want_output, error_message: 'writer requires output') \
199    .require(want_push, error_message: 'writer requires push')
200want_writer = want_minimum ? feature.enabled() : feature.allowed()
201
202feature = get_option('xptr') \
203    .require(want_xpath, error_message: 'xptr requires xpath')
204want_xptr = want_minimum ? feature.enabled() : feature.allowed()
205
206cflags_try = []
207
208### workaround for native compilers, see configure.ac
209if cc.get_argument_syntax() == 'gcc'
210    cflags_try += [
211        '-Wshadow',
212        '-Wpointer-arith',
213        '-Wcast-align',
214        '-Wwrite-strings',
215        '-Wstrict-prototypes',
216        '-Wmissing-prototypes',
217        '-Wno-long-long',
218        '-Wno-format-extra-args',
219        '-Wno-array-bounds',
220    ]
221
222    if host_machine.cpu_family() == 'alpha'
223        cflags_try += '-mieee'
224    endif
225else
226    if host_machine.cpu_family() == 'alpha'
227        cflags_try += '-ieee'
228    elif host_machine.cpu_family() == 'parisc'
229        cflags_try += '-Wp,-H30000'
230    endif
231endif
232
233foreach cf : cflags_try
234    if cc.has_argument(cf)
235        libxml2_cflags += cf
236    endif
237endforeach
238
239# configuration
240#
241# X : done
242# N : not done
243#
244# [X] config.h.in
245# [X] include/libxml/xmlversion.h.in
246# [X] libxml-2.0.pc.in
247# [X] libxml2-config.cmake.in
248# [X] python/setup.py.in
249# [N] xml2-config.in
250
251## config.h
252config_h = configuration_data()
253config_h.set_quoted('XML_SYSCONFDIR',
254                    get_option('prefix') / get_option('sysconfdir'))
255
256# header files
257xml_check_headers = [
258    [ 'stdint.h', true ],
259    [ 'poll.h', want_http ],
260]
261
262foreach header : xml_check_headers
263    if header[1] and cc.has_header(header[0])
264        config_h.set10('HAVE_' + header[0].underscorify().to_upper(), true)
265    endif
266endforeach
267
268# library functions
269xml_check_functions = [
270    # fct             | header
271    ['getentropy', 'sys/random.h'],
272    ['glob', 'glob.h'],
273    ['mmap', 'sys/mman.h'],
274]
275
276foreach function : xml_check_functions
277    config_h.set10('HAVE_DECL_' + function[0].underscorify().to_upper(),
278                   cc.has_header_symbol(function[1], function[0]))
279endforeach
280
281# library
282
283config_dir = [include_directories('.'), include_directories('include')]
284
285## dependencies
286
287xml_deps = []
288
289### math library
290if sys_windows == false
291    m_dep = cc.find_library('m', required: false)
292    if m_dep.found()
293        xml_deps += m_dep
294    endif
295endif
296
297### thread local storage
298if want_tls
299    foreach t : ['_Thread_local', '__thread', '__declspec(thread)']
300        if cc.compiles('@0@ int v;'.format(t))
301            config_h.set('XML_THREAD_LOCAL', t)
302            break
303        endif
304    endforeach
305endif
306
307### __attribute__((destructor))
308if cc.has_function_attribute('destructor')
309    config_h.set10('HAVE_FUNC_ATTRIBUTE_DESTRUCTOR', true)
310endif
311
312### DSO support
313if sys_cygwin == true
314    module_extension = '.dll'
315elif sys_windows == true
316    module_extension = '.dll'
317else
318    module_extension = '.so'
319endif
320
321if want_modules and host_machine.system() != 'windows'
322    if meson.version().version_compare('>=0.62')
323        dl_dep = dependency('dl', required: false)
324    else
325        dl_dep = cc.find_library('dl', required: false)
326    endif
327    if dl_dep.found()
328        config_h.set10('HAVE_DLOPEN', true)
329        xml_deps += dl_dep
330    endif
331endif
332
333### threads
334if want_threads
335    threads_dep = dependency('threads')
336    xml_deps += threads_dep
337else
338    threads_dep = dependency('', required: false)
339endif
340
341### xmllint shell history
342xmllint_deps = []
343
344if want_readline
345    readline_dep = dependency('readline')
346    config_h.set('HAVE_LIBREADLINE', true)
347    xmllint_deps += readline_dep
348endif
349
350if want_history
351    history_dep = dependency('history')
352    config_h.set('HAVE_LIBHISTORY', true)
353    xmllint_deps += history_dep
354endif
355
356### crypto
357if sys_windows == true
358    bcrypt_dep = cc.find_library('bcrypt', required: true)
359    xml_deps += bcrypt_dep
360endif
361
362### inet
363if want_http == true
364    if sys_windows == true
365        net_dep = cc.find_library('ws2_32', required: true)
366        xml_deps += net_dep
367    else
368        net_dep = dependency('', required: false)
369        has_in_libc = cc.has_function('gethostbyname')
370        if has_in_libc == false
371            net_dep = cc.find_library('nsl', required: true)
372            if net_dep.found()
373                has_in_nsl = cc.has_function(
374                    'gethostbyname',
375                    dependencies: net_dep,
376                    required: false,
377                )
378                if has_in_nsl == true
379                    xml_deps += net_dep
380                endif
381            endif
382        endif
383    endif
384endif
385
386### zlib
387if want_zlib
388    xml_deps += dependency('zlib')
389endif
390
391### lzma
392if want_lzma
393    xml_deps += dependency('liblzma')
394endif
395
396# icu
397if want_icu
398    icu_dep = dependency('icu-uc')
399    defs = icu_dep.get_variable(pkgconfig: 'DEFS', default_value: '')
400    if cc.has_argument(defs)
401        libxml2_cflags += defs
402    endif
403    xml_deps += icu_dep
404endif
405
406### iconv
407if want_iconv
408    xml_deps += dependency('iconv')
409endif
410
411subdir('include/libxml')
412
413# Set config_h after all subdirs and dependencies have set values
414
415configure_file(output: 'config.h', configuration: config_h)
416
417## libxml2 library
418
419xml_src = [
420    'buf.c',
421    'chvalid.c',
422    'dict.c',
423    'entities.c',
424    'encoding.c',
425    'error.c',
426    'globals.c',
427    'hash.c',
428    'list.c',
429    'parser.c',
430    'parserInternals.c',
431    'SAX2.c',
432    'threads.c',
433    'tree.c',
434    'uri.c',
435    'valid.c',
436    'xmlIO.c',
437    'xmlmemory.c',
438    'xmlstring.c',
439]
440
441xml_opt_src = [
442    [want_c14n, ['c14n.c']],
443    [want_catalog, ['catalog.c']],
444    [want_debug, ['debugXML.c']],
445    [want_html, ['HTMLparser.c', 'HTMLtree.c']],
446    [want_http, ['nanohttp.c']],
447    [want_legacy, ['legacy.c']],
448    [want_lzma, ['xzlib.c']],
449    [want_modules, ['xmlmodule.c']],
450    [want_output, ['xmlsave.c']],
451    [want_pattern, ['pattern.c']],
452    [want_reader, ['xmlreader.c']],
453    [want_regexps, ['xmlregexp.c', 'xmlunicode.c']],
454    [want_schemas, ['relaxng.c', 'xmlschemas.c', 'xmlschemastypes.c']],
455    [want_schematron, ['schematron.c']],
456    [want_writer, ['xmlwriter.c']],
457    [want_xinclude, ['xinclude.c']],
458    [want_xpath, ['xpath.c']],
459    [want_xptr, ['xlink.c', 'xpointer.c']],
460]
461
462foreach file : xml_opt_src
463    want = file[0]
464    src = file[1]
465    if want == true
466        if src.length() > 1
467            foreach s : src
468                xml_src += s
469            endforeach
470        else
471            xml_src += src
472        endif
473    endif
474endforeach
475
476v_min_compat = 0
477xml_lib = library(
478    'xml2',
479    files(xml_src),
480    c_args: libxml2_cflags,
481    dependencies: xml_deps,
482    include_directories: config_dir,
483    install: true,
484    version: meson.project_version(),
485    soversion: v_maj + v_min_compat,
486)
487
488dep_inc = include_directories('include')
489xml_dep = declare_dependency(include_directories: dep_inc, link_with: xml_lib, compile_args: dep_args)
490
491meson.override_dependency('libxml-2.0', xml_dep)
492
493## xmllint tool
494
495executable(
496    'xmllint',
497    files('xmllint.c', 'shell.c', 'lintmain.c'),
498    dependencies: [xml_dep, xmllint_deps],
499    include_directories: config_dir,
500    install: true,
501)
502
503## xmlcatalog tool
504
505if want_catalog and want_output
506    executable(
507        'xmlcatalog',
508        files('xmlcatalog.c'),
509        dependencies: [xml_dep, xmllint_deps],
510        include_directories: config_dir,
511        install: true,
512    )
513endif
514
515## testdso module
516
517testdso_mod = shared_module(
518    'testdso',
519    files('testdso.c'),
520    build_rpath: get_option('libdir'),
521    include_directories: config_dir,
522    name_prefix: '',
523)
524
525## tests
526
527checks = {
528    'runsuite': [],
529    'runtest': threads_dep,
530    'runxmlconf': [],
531# Disabled for now, see #694
532#    'testModule': [],
533    'testapi': [],
534    'testchar': [],
535    'testdict': [],
536    'testlimits': [],
537    'testparser': [],
538    'testrecurse': [],
539}
540
541foreach check, deps : checks
542    exe = executable(
543        check,
544        files(check + '.c'),
545        dependencies: [deps, xml_dep],
546        include_directories: config_dir,
547    )
548    if check != 'testlimits'
549        test(check, exe, timeout: 0, workdir: meson.current_source_dir())
550    endif
551endforeach
552
553subdir('example')
554subdir('doc')
555
556if want_python == true
557    subdir('python')
558endif
559
560## pc files
561
562pkgmod = import('pkgconfig')
563
564pkgmod.generate(
565    xml_lib,
566    description: 'libXML library version2.',
567    filebase: 'libxml-2.0',
568    name: 'libXML',
569    subdirs:  [meson.project_name()],
570    variables: 'modules=' + want_modules.to_string('1', '0'),
571)
572
573## libxml2-config.cmake file
574
575config_cmake = configuration_data()
576config_cmake.set('LIBXML_MAJOR_VERSION', v_maj)
577config_cmake.set('LIBXML_MINOR_VERSION', v_min)
578config_cmake.set('LIBXML_MICRO_VERSION', v_mic)
579config_cmake.set('VERSION', meson.project_version())
580config_cmake.set('WITH_HTTP', want_http.to_int().to_string())
581config_cmake.set('WITH_ICONV', want_iconv.to_int().to_string())
582config_cmake.set('WITH_ICU', want_icu.to_int().to_string())
583config_cmake.set('WITH_LZMA', want_lzma.to_int().to_string())
584config_cmake.set('WITH_MODULES', want_modules.to_int().to_string())
585config_cmake.set('WITH_THREADS', want_threads.to_int().to_string())
586config_cmake.set('WITH_ZLIB', want_zlib.to_int().to_string())
587config_cmake.set('XML_CFLAGS', xml_cflags)
588configure_file(
589    input: 'libxml2-config.cmake.in',
590    output: 'libxml2-config.cmake',
591    configuration: config_cmake,
592    install_dir: dir_lib / 'cmake' / 'libxml2',
593)
594
595# summary
596
597summary(
598    {
599        'OS': host_os,
600        'c14n': want_c14n,
601        'catalog': want_catalog,
602        'debug': want_debug,
603        'history': want_history,
604        'html': want_html,
605        'http': want_http,
606        'iconv': want_iconv,
607        'icu': want_icu,
608        'iso8859x': want_iso8859x,
609        'legacy': want_legacy,
610        'lzma': want_lzma,
611        'modules': want_modules,
612        'output': want_output,
613        'pattern': want_pattern,
614        'push': want_push,
615        'python': want_python,
616        'reader': want_reader,
617        'readline': want_readline,
618        'regexps': want_regexps,
619        'sax1': want_sax1,
620        'schemas': want_schemas,
621        'schematron': want_schematron,
622        'threads': want_threads,
623        'thread-alloc': want_thread_alloc,
624        'tls': want_tls,
625        'valid': want_valid,
626        'writer': want_writer,
627        'xinclude': want_xinclude,
628        'xpath': want_xpath,
629        'xptr': want_xptr,
630        'zlib': want_zlib,
631    },
632    section: 'Configuration Options Summary:',
633)
634