• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#                          __  __            _
2#                       ___\ \/ /_ __   __ _| |_
3#                      / _ \\  /| '_ \ / _` | __|
4#                     |  __//  \| |_) | (_| | |_
5#                      \___/_/\_\ .__/ \__,_|\__|
6#                               |_| XML parser
7#
8# Copyright (c) 2010      Patrick Spendrin <ps_ml@gmx.de>
9# Copyright (c) 2012      Karl Waclawek <karl@waclawek.net>
10# Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
11# Copyright (c) 2016      Sergei Nikulov <sergey.nikulov@gmail.com>
12# Copyright (c) 2016      Björn Lindahl <bjorn.lindahl@foi.se>
13# Copyright (c) 2016      Tobias Taschner <github@tc84.de>
14# Copyright (c) 2016      Ben Boeckel <ben.boeckel@kitware.com>
15# Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
16# Copyright (c) 2017      Rolf Eike Beer <eike@sf-mail.de>
17# Copyright (c) 2017      Stephen Groat <stephen@groat.us>
18# Copyright (c) 2017      Franek Korta <fkorta@gmail.com>
19# Copyright (c) 2018      pedro-vicente <pedro.vicente@space-research.org>
20# Copyright (c) 2018      Frank Rast <frank.rast@gefeg.com>
21# Copyright (c) 2018      userwithuid <userwithuid@gmail.com>
22# Copyright (c) 2018      Yury Gribov <tetra2005@gmail.com>
23# Copyright (c) 2019      Kishore Kunche <kishore.kunche@intel.com>
24# Copyright (c) 2019      xantares <xantares09@hotmail.com>
25# Copyright (c) 2019      Mohammed Khajapasha <mohammed.khajapasha@intel.com>
26# Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
27# Copyright (c) 2019      Bhargava Shastry <bhargava.shastry@ethereum.org>
28# Copyright (c) 2020      Maciej Sroczyński <macieksroczynski@poczta.fm>
29# Copyright (c) 2020      Gulliver <gulliver@traumkristalle.net>
30# Copyright (c) 2020      Thomas Beutlich <tc@tbeu.de>
31# Copyright (c) 2021      Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
32# Unlike most of Expat,
33# this file is copyrighted under the BSD-license for buildsystem files of KDE.
34
35cmake_minimum_required(VERSION 3.1.3)
36
37# This allows controlling documented build time switches
38# when Expat is pulled in using the add_subdirectory function, e.g.
39#
40#   set(EXPAT_BUILD_DOCS OFF)
41#   set(EXPAT_BUILD_TOOLS OFF)
42#   add_subdirectory(${expat_SOURCE_DIR}/expat ${expat_BINARY_DIR})
43#
44# would disable compilation of the xmlwf CLI and its man page.
45# Without activating behaviour NEW for policy CMP0077 here,
46# a user with -Wdev enabled would see warning
47#
48#   Policy CMP0077 is not set: option() honors normal variables.  Run "cmake
49#   --help-policy CMP0077" for policy details.  Use the cmake_policy command to
50#   set the policy and suppress this warning.
51#
52#   For compatibility with older versions of CMake, option is clearing the
53#   normal variable 'EXPAT_BUILD_DOCS'.
54#
55# and effectively not be able to adjust option EXPAT_BUILD_DOCS.
56#
57# For more details please see:
58# - https://cmake.org/cmake/help/latest/policy/CMP0077.html
59# - https://github.com/libexpat/libexpat/pull/419
60#
61if(POLICY CMP0077)
62    cmake_policy(SET CMP0077 NEW)
63endif()
64
65project(expat
66    VERSION
67        2.4.1
68    LANGUAGES
69        C
70)
71
72set(PACKAGE_BUGREPORT "expat-bugs@libexpat.org")
73set(PACKAGE_NAME "expat")
74set(PACKAGE_VERSION "${PROJECT_VERSION}")
75set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
76set(PACKAGE_TARNAME "${PACKAGE_NAME}")
77
78include(CMakePackageConfigHelpers)
79include(GNUInstallDirs)
80
81#
82# Configuration defaults
83#
84if(WINCE)
85    set(_EXPAT_BUILD_TOOLS_DEFAULT OFF)
86else()
87    set(_EXPAT_BUILD_TOOLS_DEFAULT ON)
88endif()
89if(MSVC OR NOT _EXPAT_BUILD_TOOLS_DEFAULT)
90    set(_EXPAT_BUILD_DOCS_DEFAULT OFF)
91else()
92    find_program(DOCBOOK_TO_MAN NAMES docbook2x-man db2x_docbook2man docbook2man docbook-to-man)
93    if(DOCBOOK_TO_MAN)
94        set(_EXPAT_BUILD_DOCS_DEFAULT ON)
95    else()
96        set(_EXPAT_BUILD_DOCS_DEFAULT OFF)
97    endif()
98endif()
99if(MSVC)
100    set(_EXPAT_BUILD_PKGCONFIG_DEFAULT OFF)
101else()
102    set(_EXPAT_BUILD_PKGCONFIG_DEFAULT ON)
103endif()
104if(DEFINED BUILD_SHARED_LIBS)
105    set(_EXPAT_SHARED_LIBS_DEFAULT ${BUILD_SHARED_LIBS})
106else()
107    set(_EXPAT_SHARED_LIBS_DEFAULT ON)
108endif()
109
110#
111# Configuration
112#
113option(EXPAT_BUILD_TOOLS "build the xmlwf tool for expat library" ${_EXPAT_BUILD_TOOLS_DEFAULT})
114option(EXPAT_BUILD_EXAMPLES "build the examples for expat library" ON)
115option(EXPAT_BUILD_TESTS "build the tests for expat library" ON)
116option(EXPAT_SHARED_LIBS "build a shared expat library" ${_EXPAT_SHARED_LIBS_DEFAULT})
117option(EXPAT_BUILD_DOCS "build man page for xmlwf" ${_EXPAT_BUILD_DOCS_DEFAULT})
118option(EXPAT_BUILD_FUZZERS "build fuzzers for the expat library" OFF)
119option(EXPAT_BUILD_PKGCONFIG "build pkg-config file" ${_EXPAT_BUILD_PKGCONFIG_DEFAULT})
120option(EXPAT_OSSFUZZ_BUILD "build fuzzers via ossfuzz for the expat library" OFF)
121if(UNIX OR _EXPAT_HELP)
122    option(EXPAT_WITH_LIBBSD "utilize libbsd (for arc4random_buf)" OFF)
123endif()
124option(EXPAT_ENABLE_INSTALL "install expat files in cmake install target" ON)
125set(EXPAT_CONTEXT_BYTES 1024 CACHE STRING "Define to specify how much context to retain around the current parse point")
126mark_as_advanced(EXPAT_CONTEXT_BYTES)
127option(EXPAT_DTD "Define to make parameter entity parsing functionality available" ON)
128mark_as_advanced(EXPAT_DTD)
129option(EXPAT_NS "Define to make XML Namespaces functionality available" ON)
130mark_as_advanced(EXPAT_NS)
131option(EXPAT_WARNINGS_AS_ERRORS "Treat all compiler warnings as errors" OFF)
132if(UNIX OR _EXPAT_HELP)
133    option(EXPAT_DEV_URANDOM "Define to include code reading entropy from `/dev/urandom'." ON)
134    set(EXPAT_WITH_GETRANDOM "AUTO" CACHE STRING
135            "Make use of getrandom function (ON|OFF|AUTO) [default=AUTO]")
136    set(EXPAT_WITH_SYS_GETRANDOM "AUTO" CACHE STRING
137            "Make use of syscall SYS_getrandom (ON|OFF|AUTO) [default=AUTO]")
138    mark_as_advanced(EXPAT_DEV_URANDOM)
139endif()
140set(EXPAT_CHAR_TYPE "char" CACHE STRING "Character type to use (char|ushort|wchar_t) [default=char]")
141option(EXPAT_ATTR_INFO "Define to allow retrieving the byte offsets for attribute names and values" OFF)
142mark_as_advanced(EXPAT_ATTR_INFO)
143option(EXPAT_LARGE_SIZE "Make XML_GetCurrent* functions return <(unsigned) long long> rather than <(unsigned) long>" OFF)
144mark_as_advanced(EXPAT_LARGE_SIZE)
145option(EXPAT_MIN_SIZE "Get a smaller (but slower) parser (in particular avoid multiple copies of the tokenizer)" OFF)
146mark_as_advanced(EXPAT_MIN_SIZE)
147if(MSVC OR _EXPAT_HELP)
148    set(EXPAT_MSVC_STATIC_CRT OFF CACHE BOOL "Use /MT flag (static CRT) when compiling in MSVC")
149endif()
150
151if(EXPAT_BUILD_TESTS)
152    # We have to call enable_language() before modifying any CMAKE_CXX_* variables
153    enable_language(CXX)
154endif()
155
156#
157# Environment checks
158#
159if(EXPAT_WITH_LIBBSD)
160    find_library(LIB_BSD NAMES bsd)
161    if(NOT LIB_BSD)
162        message(SEND_ERROR "EXPAT_WITH_LIBBSD option is enabled, but libbsd was not found")
163    else()
164        set(HAVE_LIBBSD TRUE)
165    endif()
166endif()
167
168if(MSVC)
169    # For the three types of MSVC version values, please see:
170    # - https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html
171    # - https://sourceforge.net/p/predef/wiki/Compilers/
172    # - https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History
173    set(_EXPAT_MSVC_REQUIRED_INT 1800)  # i.e. 12.0/2013/1800; see PR #426
174    set(_EXPAT_MSVC_SUPPORTED_INT 1910)
175    set(_EXPAT_MSVC_SUPPORTED_DISPLAY "Visual Studio 15.0/2017/${_EXPAT_MSVC_SUPPORTED_INT}")
176
177    if(MSVC_VERSION VERSION_LESS ${_EXPAT_MSVC_SUPPORTED_INT})
178        if(MSVC_VERSION VERSION_LESS ${_EXPAT_MSVC_REQUIRED_INT})
179            message(SEND_ERROR "MSVC_VERSION ${MSVC_VERSION} is TOO OLD to compile Expat without errors.")
180            message(SEND_ERROR "Please use officially supported ${_EXPAT_MSVC_SUPPORTED_DISPLAY} or later.  Thank you!")
181        else()
182            message(WARNING "MSVC_VERSION ${MSVC_VERSION} is NOT OFFICIALLY SUPPORTED by Expat.")
183            message(WARNING "Please use ${_EXPAT_MSVC_SUPPORTED_DISPLAY} or later.  Thank you!")
184        endif()
185    endif()
186endif()
187
188macro(_expat_copy_bool_int source_ref dest_ref)
189    if(${source_ref})
190        set(${dest_ref} 1)
191    else()
192        set(${dest_ref} 0)
193    endif()
194endmacro()
195
196if(EXPAT_LARGE_SIZE)
197    add_definitions(-DXML_LARGE_SIZE)
198endif()
199
200if(EXPAT_MIN_SIZE)
201    add_definitions(-DXML_MIN_SIZE)
202endif()
203
204if(EXPAT_CHAR_TYPE STREQUAL "char")
205    set(_EXPAT_UNICODE OFF)
206    set(_EXPAT_UNICODE_WCHAR_T OFF)
207elseif(EXPAT_CHAR_TYPE STREQUAL "ushort")
208    set(_EXPAT_UNICODE ON)
209    set(_EXPAT_UNICODE_WCHAR_T OFF)
210    if(EXPAT_BUILD_EXAMPLES)
211        message(SEND_ERROR "Examples can not be built with option -DEXPAT_CHAR_TYPE=ushort. Please pass -DEXPAT_CHAR_TYPE=(char|wchar_t) or -DEXPAT_BUILD_EXAMPLES=OFF.")
212    endif()
213    if(EXPAT_BUILD_TESTS)
214        message(SEND_ERROR "The testsuite can not be built with option -DEXPAT_CHAR_TYPE=ushort. Please pass -DEXPAT_CHAR_TYPE=(char|wchar_t) or -DEXPAT_BUILD_TESTS=OFF.")
215    endif()
216    if(EXPAT_BUILD_TOOLS)
217        message(SEND_ERROR "The xmlwf tool can not be built with option -DEXPAT_CHAR_TYPE=ushort. Please pass -DEXPAT_CHAR_TYPE=(char|wchar_t) or -DEXPAT_BUILD_TOOLS=OFF.")
218    endif()
219elseif(EXPAT_CHAR_TYPE STREQUAL "wchar_t")
220    set(_EXPAT_UNICODE ON)
221    set(_EXPAT_UNICODE_WCHAR_T ON)
222    if(NOT WIN32)
223        string(FIND "${CMAKE_C_FLAGS}" "-fshort-wchar" _expat_short_wchar_found)
224        if(${_expat_short_wchar_found} EQUAL "-1")
225            message(SEND_ERROR "Configuration -DEXPAT_CHAR_TYPE=wchar_t requires -DCMAKE_{C,CXX}_FLAGS=-fshort-wchar (which was not found) and libc compiled with -fshort-wchar, too.")
226        endif()
227        if (EXPAT_BUILD_TOOLS)
228            message(SEND_ERROR "The xmlwf tool can not be built with option -DEXPAT_CHAR_TYPE=wchar_t outside of Windows. Please pass -DEXPAT_CHAR_TYPE=char or -DEXPAT_BUILD_TOOLS=OFF.")
229        endif()
230    endif()
231else()
232    message(SEND_ERROR "Option -DEXPAT_CHAR_TYPE=(char|ushort|wchar_t) cannot be \"${EXPAT_CHAR_TYPE}\".")
233endif()
234
235if(_EXPAT_UNICODE)
236    add_definitions(-DXML_UNICODE)              # for unsigned short
237    if(_EXPAT_UNICODE_WCHAR_T)
238        add_definitions(-DXML_UNICODE_WCHAR_T)  # for wchar_t
239    endif()
240endif()
241
242include(${CMAKE_CURRENT_LIST_DIR}/ConfigureChecks.cmake)
243
244macro(evaluate_detection_results use_ref have_ref thing_lower thing_title)
245    if(${use_ref} AND NOT (${use_ref} STREQUAL "AUTO") AND NOT ${have_ref})
246        message(SEND_ERROR
247                "Use of ${thing_lower} was enforced by ${use_ref}=ON but it could not be found.")
248    elseif(NOT ${use_ref} AND ${have_ref})
249        message("${thing_title} was found but it will not be used due to ${use_ref}=OFF.")
250        set(${have_ref} 0)
251    endif()
252endmacro()
253
254if(NOT WIN32)
255    evaluate_detection_results(EXPAT_WITH_GETRANDOM HAVE_GETRANDOM "function getrandom" "Function getrandom")
256    evaluate_detection_results(EXPAT_WITH_SYS_GETRANDOM HAVE_SYSCALL_GETRANDOM "syscall SYS_getrandom" "Syscall SYS_getrandom")
257endif()
258
259_expat_copy_bool_int(EXPAT_ATTR_INFO        XML_ATTR_INFO)
260_expat_copy_bool_int(EXPAT_DTD              XML_DTD)
261_expat_copy_bool_int(EXPAT_LARGE_SIZE       XML_LARGE_SIZE)
262_expat_copy_bool_int(EXPAT_MIN_SIZE         XML_MIN_SIZE)
263_expat_copy_bool_int(EXPAT_NS               XML_NS)
264if(NOT WIN32)
265    _expat_copy_bool_int(EXPAT_DEV_URANDOM  XML_DEV_URANDOM)
266endif()
267set(XML_CONTEXT_BYTES ${EXPAT_CONTEXT_BYTES})
268
269macro(expat_install)
270    if(EXPAT_ENABLE_INSTALL)
271        install(${ARGN})
272    endif()
273endmacro()
274
275configure_file(expat_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/expat_config.h")
276expat_install(FILES "${CMAKE_CURRENT_BINARY_DIR}/expat_config.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
277
278
279set(EXTRA_COMPILE_FLAGS)
280if(FLAG_NO_STRICT_ALIASING)
281    set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fno-strict-aliasing")
282endif()
283if(FLAG_VISIBILITY)
284  add_definitions(-DXML_ENABLE_VISIBILITY=1)
285  set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fvisibility=hidden")
286endif()
287if(MINGW)
288    # Without __USE_MINGW_ANSI_STDIO the compiler produces a false positive
289    set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Wno-pedantic-ms-format")
290endif()
291if (EXPAT_WARNINGS_AS_ERRORS)
292    if(MSVC)
293        add_definitions(/WX)
294    else()
295        set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -Werror")
296    endif()
297endif()
298set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}")
299set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}")
300
301if (MSVC)
302    if (EXPAT_MSVC_STATIC_CRT)
303        message("-- Using static CRT ${EXPAT_MSVC_STATIC_CRT}")
304        foreach(flag_var
305                CMAKE_CXX_FLAGS_DEBUG
306                CMAKE_CXX_FLAGS_RELEASE
307                CMAKE_CXX_FLAGS_MINSIZEREL
308                CMAKE_CXX_FLAGS_RELWITHDEBINFO
309                CMAKE_C_FLAGS_DEBUG
310                CMAKE_C_FLAGS_RELEASE
311                CMAKE_C_FLAGS_MINSIZEREL
312                CMAKE_C_FLAGS_RELWITHDEBINFO
313                )
314            string(REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
315        endforeach()
316    endif()
317endif()
318
319include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib)
320if(MSVC)
321    add_definitions(-D_CRT_SECURE_NO_WARNINGS -wd4996)
322endif()
323if(WIN32)
324    if(_EXPAT_UNICODE_WCHAR_T)
325        set(_POSTFIX_WIDE "w")
326    endif()
327
328    if(MSVC AND NOT EXPAT_SHARED_LIBS)
329        if(EXPAT_MSVC_STATIC_CRT)
330            set(_POSTFIX_CRT "MT")
331        else()
332            set(_POSTFIX_CRT "MD")
333        endif()
334    endif()
335
336    foreach(postfix_var
337            CMAKE_DEBUG_POSTFIX
338            CMAKE_RELEASE_POSTFIX
339            CMAKE_MINSIZEREL_POSTFIX
340            CMAKE_RELWITHDEBINFO_POSTFIX
341            )
342        if(postfix_var STREQUAL "CMAKE_DEBUG_POSTFIX")
343            set(_POSTFIX_DEBUG "d")
344        else()
345            set(_POSTFIX_DEBUG "")
346        endif()
347
348        set(${postfix_var} "${_POSTFIX_WIDE}${_POSTFIX_DEBUG}${_POSTFIX_CRT}" CACHE STRING "Windows binary postfix, e.g. libexpat<postfix=[w][d][MD|MT]>.lib")
349    endforeach()
350endif()
351
352#
353# C library
354#
355set(expat_SRCS
356    lib/xmlparse.c
357    lib/xmlrole.c
358    lib/xmltok.c
359# NOTE: ISO C forbids an empty translation unit
360#   lib/xmltok_impl.c
361#   lib/xmltok_ns.c
362)
363
364if(EXPAT_SHARED_LIBS)
365    set(_SHARED SHARED)
366    if(MSVC)
367        set(expat_SRCS ${expat_SRCS} lib/libexpat.def)
368    endif()
369else()
370    set(_SHARED STATIC)
371endif()
372
373# Avoid colliding with Expat.dll of Perl's XML::Parser::Expat
374if(WIN32 AND NOT MINGW)
375    set(_EXPAT_OUTPUT_NAME libexpat)  # CMAKE_*_POSTFIX applies, see above
376else()
377    if(_EXPAT_UNICODE)
378        set(_EXPAT_OUTPUT_NAME expatw)
379    else()
380        set(_EXPAT_OUTPUT_NAME expat)
381    endif()
382endif()
383
384add_library(expat ${_SHARED} ${expat_SRCS})
385if(EXPAT_WITH_LIBBSD)
386    target_link_libraries(expat ${LIB_BSD})
387endif()
388
389set(LIBCURRENT 9)   # sync
390set(LIBREVISION 1)  # with
391set(LIBAGE 8)       # configure.ac!
392math(EXPR LIBCURRENT_MINUS_AGE "${LIBCURRENT} - ${LIBAGE}")
393
394set_property(TARGET expat PROPERTY OUTPUT_NAME "${_EXPAT_OUTPUT_NAME}")
395if(NOT WIN32)
396    set_property(TARGET expat PROPERTY VERSION ${LIBCURRENT_MINUS_AGE}.${LIBAGE}.${LIBREVISION})
397    set_property(TARGET expat PROPERTY SOVERSION ${LIBCURRENT_MINUS_AGE})
398    set_property(TARGET expat PROPERTY NO_SONAME ${NO_SONAME})
399endif()
400
401target_include_directories(expat
402    INTERFACE
403        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>
404        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
405        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
406)
407
408if(NOT EXPAT_SHARED_LIBS AND WIN32)
409    target_compile_definitions(expat PUBLIC -DXML_STATIC)
410endif()
411
412expat_install(TARGETS expat EXPORT expat
413                      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
414                      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
415                      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
416
417expat_install(FILES lib/expat.h lib/expat_external.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
418
419#
420# pkg-config file
421#
422if(EXPAT_BUILD_PKGCONFIG)
423    set(prefix ${CMAKE_INSTALL_PREFIX})
424    set(exec_prefix "\${prefix}")
425
426    if(CMAKE_INSTALL_LIBDIR MATCHES "^/")
427        set(libdir "${CMAKE_INSTALL_LIBDIR}")
428    else()
429        set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
430    endif()
431
432    if(CMAKE_INSTALL_INCLUDEDIR MATCHES "^/")
433        set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
434    else()
435        set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
436    endif()
437
438    configure_file(expat.pc.in ${CMAKE_CURRENT_BINARY_DIR}/expat.pc @ONLY)
439    expat_install(FILES ${CMAKE_CURRENT_BINARY_DIR}/expat.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
440endif()
441
442#
443# C command line tool xmlwf
444#
445if(EXPAT_BUILD_TOOLS)
446    set(xmlwf_SRCS
447        xmlwf/xmlwf.c
448        xmlwf/xmlfile.c
449        xmlwf/codepage.c
450        xmlwf/readfilemap.c
451    )
452
453    add_executable(xmlwf ${xmlwf_SRCS})
454    set_property(TARGET xmlwf PROPERTY RUNTIME_OUTPUT_DIRECTORY xmlwf)
455    target_link_libraries(xmlwf expat)
456    expat_install(TARGETS xmlwf DESTINATION ${CMAKE_INSTALL_BINDIR})
457
458    if(MINGW AND _EXPAT_UNICODE_WCHAR_T)
459        # https://gcc.gnu.org/onlinedocs/gcc/x86-Windows-Options.html
460        set_target_properties(xmlwf PROPERTIES LINK_FLAGS -municode)
461    endif()
462
463    if(EXPAT_BUILD_DOCS)
464        file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/doc)
465        add_custom_target(
466            xmlwf-manpage
467            COMMAND
468                "${DOCBOOK_TO_MAN}" "${PROJECT_SOURCE_DIR}/doc/xmlwf.xml" && mv "XMLWF.1" "${PROJECT_BINARY_DIR}/doc/xmlwf.1"
469            BYPRODUCTS
470                doc/xmlwf.1)
471        add_dependencies(expat xmlwf-manpage)
472        expat_install(FILES "${PROJECT_BINARY_DIR}/doc/xmlwf.1" DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
473    elseif(EXISTS ${PROJECT_SOURCE_DIR}/doc/xmlwf.1)
474        expat_install(FILES "${PROJECT_SOURCE_DIR}/doc/xmlwf.1" DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
475    endif()
476endif()
477
478#
479# C code examples
480#
481if(EXPAT_BUILD_EXAMPLES)
482    add_executable(elements examples/elements.c)
483    set_property(TARGET elements PROPERTY RUNTIME_OUTPUT_DIRECTORY examples)
484    target_link_libraries(elements expat)
485
486    add_executable(outline examples/outline.c)
487    set_property(TARGET outline PROPERTY RUNTIME_OUTPUT_DIRECTORY examples)
488    target_link_libraries(outline expat)
489endif()
490
491#
492# C/C++ test runners
493#
494if(EXPAT_BUILD_TESTS)
495    ## these are unittests that can be run on any platform
496    enable_testing()
497
498    set(test_SRCS
499        tests/chardata.c
500        tests/memcheck.c
501        tests/minicheck.c
502        tests/structdata.c
503        ${expat_SRCS}
504    )
505
506    if(NOT MSVC)
507        if(MINGW)
508            set(host whatever-mingw32)  # for nothing but run.sh
509        endif()
510        configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run.sh.in run.sh @ONLY)
511    endif()
512
513    function(expat_add_test _name _file)
514        if(MSVC)
515            add_test(NAME ${_name} COMMAND ${_file})
516        else()
517            add_test(NAME ${_name} COMMAND bash run.sh ${_file})
518        endif()
519    endfunction()
520
521    add_executable(runtests tests/runtests.c ${test_SRCS})
522    set_property(TARGET runtests PROPERTY RUNTIME_OUTPUT_DIRECTORY tests)
523    expat_add_test(runtests $<TARGET_FILE:runtests>)
524
525    add_executable(runtestspp tests/runtestspp.cpp ${test_SRCS})
526    set_property(TARGET runtestspp PROPERTY RUNTIME_OUTPUT_DIRECTORY tests)
527    expat_add_test(runtestspp $<TARGET_FILE:runtestspp>)
528
529    if(EXPAT_WITH_LIBBSD)
530        target_link_libraries(runtests ${LIB_BSD})
531        target_link_libraries(runtestspp ${LIB_BSD})
532    endif()
533endif()
534
535if(EXPAT_BUILD_FUZZERS)
536    if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
537        message(SEND_ERROR
538            "Building fuzz targets without Clang (but ${CMAKE_C_COMPILER_ID}) "
539            "is not supported. Please set "
540            "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++.")
541    endif()
542
543    string(FIND "${CMAKE_C_FLAGS}" "-fsanitize" sanitizer_present)
544    if(${sanitizer_present} EQUAL "-1")
545        message(WARNING
546            "There was no sanitizer present when building the fuzz targets. "
547            "This is likely in error - consider adding "
548            "-DCMAKE_C_FLAGS='-fsanitize=<sanitizer>' and "
549            "-DCMAKE_CXX_FLAGS='-fsanitize=<sanitizer>' and "
550            "-DCMAKE_EXE_LINKER_FLAGS='-fsanitize=<sanitizer>' and "
551            "-DCMAKE_MODULE_LINKER_FLAGS='-fsanitize=<sanitizer>' and "
552            "-DCMAKE_SHARED_LINKER_FLAGS='-fsanitize=<sanitizer>' to your cmake "
553            "execution.")
554    endif()
555
556    if(EXPAT_OSSFUZZ_BUILD AND NOT DEFINED ENV{LIB_FUZZING_ENGINE})
557        message(SEND_ERROR
558            "OSS-Fuzz builds require the environment variable "
559            "LIB_FUZZING_ENGINE to be set. If you are seeing this "
560            "warning, it points to a deeper problem in the ossfuzz "
561            "build setup.")
562    endif()
563
564    set(encoding_types UTF-16 UTF-8 ISO-8859-1 US-ASCII UTF-16BE UTF-16LE)
565    set(fuzz_targets xml_parse_fuzzer xml_parsebuffer_fuzzer)
566
567    add_library(fuzzpat STATIC ${expat_SRCS})
568    if(NOT EXPAT_OSSFUZZ_BUILD)
569        target_compile_options(fuzzpat PRIVATE -fsanitize=fuzzer-no-link)
570    endif()
571
572    foreach(fuzz_target ${fuzz_targets})
573        foreach(encoding_type ${encoding_types})
574            set(target_name ${fuzz_target}_${encoding_type})
575            add_executable(${target_name} fuzz/${fuzz_target}.c)
576            target_link_libraries(${target_name} fuzzpat)
577            target_compile_definitions(${target_name}
578                PRIVATE ENCODING_FOR_FUZZING=${encoding_type})
579            if(NOT EXPAT_OSSFUZZ_BUILD)
580                target_compile_options(${target_name} PRIVATE -fsanitize=fuzzer-no-link)
581            endif()
582            # NOTE: Avoiding target_link_options here only because it needs CMake >=3.13
583            if(EXPAT_OSSFUZZ_BUILD)
584                set_target_properties(${target_name} PROPERTIES LINK_FLAGS $ENV{LIB_FUZZING_ENGINE})
585                set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE "CXX")
586            else()
587                set_target_properties(${target_name} PROPERTIES LINK_FLAGS -fsanitize=fuzzer)
588            endif()
589            set_property(
590                TARGET ${target_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY fuzz)
591        endforeach()
592    endforeach()
593else()
594    if(EXPAT_OSSFUZZ_BUILD)
595        message(SEND_ERROR
596                "Attempting to perform an ossfuzz build without turning on the fuzzer build. "
597                "This is likely in error - consider adding "
598                "-DEXPAT_BUILD_FUZZERS=ON to your cmake execution.")
599    endif()
600endif()
601
602#
603# Custom target "run-xmltest"
604#
605if(EXPAT_BUILD_TOOLS AND NOT MSVC)
606    add_custom_target(
607        xmlts-zip-downloaded
608        COMMAND
609            sh -c 'test -f xmlts.zip || wget --output-document=xmlts.zip https://www.w3.org/XML/Test/xmlts20080827.zip'
610        BYPRODUCTS
611            tests/xmlts.zip
612        WORKING_DIRECTORY
613            tests/)
614
615    add_custom_target(
616        xmlts-zip-extracted
617        COMMAND
618            sh -c 'test -d xmlconf || unzip -q xmlts.zip'
619        BYPRODUCTS
620            tests/xmlconf
621        WORKING_DIRECTORY
622            tests/)
623    add_dependencies(xmlts-zip-extracted xmlts-zip-downloaded)
624
625    add_custom_target(
626        xmltest-sh-been-run
627        COMMAND
628            sh -c '${CMAKE_CURRENT_SOURCE_DIR}/tests/xmltest.sh "bash ${CMAKE_CURRENT_BINARY_DIR}/run.sh $<TARGET_FILE:xmlwf>" 2>&1 | tee tests/xmltest.log'
629        BYPRODUCTS
630            tests/xmltest.log)
631    add_dependencies(xmltest-sh-been-run xmlts-zip-extracted xmlwf)
632
633    add_custom_target(
634        xmltest-log-fixed
635        COMMAND
636            ${CMAKE_CURRENT_SOURCE_DIR}/fix-xmltest-log.sh tests/xmltest.log
637        DEPENDS
638            tests/xmltest.log)
639    add_dependencies(xmltest-log-fixed xmltest-sh-been-run)
640
641    add_custom_target(
642        xmltest-log-verified
643        COMMAND
644            diff -u ${CMAKE_CURRENT_SOURCE_DIR}/tests/xmltest.log.expected tests/xmltest.log)
645    add_dependencies(xmltest-log-verified xmltest-log-fixed)
646
647    add_custom_target(run-xmltest)
648    add_dependencies(run-xmltest xmltest-log-verified)
649endif()
650
651#
652# Documentation
653#
654configure_file(Changes changelog COPYONLY)
655expat_install(
656    FILES
657        AUTHORS
658        ${CMAKE_CURRENT_BINARY_DIR}/changelog
659    DESTINATION
660        ${CMAKE_INSTALL_DOCDIR})
661
662#
663# CMake files for find_package(expat [..] CONFIG [..])
664#
665configure_package_config_file(
666        cmake/expat-config.cmake.in
667        cmake/expat-config.cmake
668    INSTALL_DESTINATION
669        ${CMAKE_INSTALL_LIBDIR}/cmake/expat-${PROJECT_VERSION}/
670)
671write_basic_package_version_file(
672    cmake/expat-config-version.cmake
673    COMPATIBILITY SameMajorVersion  # i.e. semver
674)
675export(
676    TARGETS
677        expat
678    FILE
679        cmake/expat-targets.cmake  # not going to be installed
680)
681expat_install(
682    FILES
683        ${CMAKE_CURRENT_BINARY_DIR}/cmake/expat-config.cmake
684        ${CMAKE_CURRENT_BINARY_DIR}/cmake/expat-config-version.cmake
685    DESTINATION
686        ${CMAKE_INSTALL_LIBDIR}/cmake/expat-${PROJECT_VERSION}/
687)
688expat_install(
689    EXPORT
690        expat
691    DESTINATION
692        ${CMAKE_INSTALL_LIBDIR}/cmake/expat-${PROJECT_VERSION}/
693    NAMESPACE
694        expat::
695)
696
697#
698# CPack
699#
700
701# This effectively disables target "package_source".
702# That is done due to CPack's unfortunate choice of an exclusion list
703# rather than inclusion list.  An exclusion list does not protect against
704# unwanted files ending up in the resulting archive in a way that's
705# safe to run from an Expat developer's machine.
706set(CPACK_SOURCE_GENERATOR '')
707
708if(WIN32)
709    set(CPACK_GENERATOR ZIP)
710else()
711    set(CPACK_GENERATOR TGZ)
712endif()
713
714include(CPack)
715
716#
717# Summary
718#
719if(EXPAT_CHAR_TYPE STREQUAL "char")
720    set(_EXPAT_CHAR_TYPE_SUMMARY "char (UTF-8)")
721elseif(EXPAT_CHAR_TYPE STREQUAL "ushort")
722    set(_EXPAT_CHAR_TYPE_SUMMARY "ushort (unsigned short, UTF-16)")
723elseif(EXPAT_CHAR_TYPE STREQUAL "wchar_t")
724    if(WIN32)
725        set(_EXPAT_CHAR_TYPE_SUMMARY "wchar_t (UTF-16)")
726    else()
727        set(_EXPAT_CHAR_TYPE_SUMMARY "wchar_t (UTF-32)  // not implemented")
728    endif()
729else()
730    set(_EXPAT_CHAR_TYPE_SUMMARY "ERROR")
731endif()
732string(TOUPPER "${CMAKE_BUILD_TYPE}" _EXPAT_BUILD_TYPE_UPPER)
733
734message(STATUS "===========================================================================")
735message(STATUS "")
736message(STATUS "Configuration")
737message(STATUS "  Prefix ..................... ${CMAKE_INSTALL_PREFIX}")
738message(STATUS "  Build type ................. ${CMAKE_BUILD_TYPE}")
739message(STATUS "  Shared libraries ........... ${EXPAT_SHARED_LIBS}")
740if(MSVC)
741    message(STATUS "  Static CRT ................. ${EXPAT_MSVC_STATIC_CRT}")
742endif()
743message(STATUS "  Character type ............. ${_EXPAT_CHAR_TYPE_SUMMARY}")
744if(WIN32)
745    message(STATUS "  Binary postfix ............. ${CMAKE_${_EXPAT_BUILD_TYPE_UPPER}_POSTFIX}")
746endif()
747message(STATUS "")
748message(STATUS "  Build documentation ........ ${EXPAT_BUILD_DOCS}")
749message(STATUS "  Build examples ............. ${EXPAT_BUILD_EXAMPLES}")
750message(STATUS "  Build fuzzers .............. ${EXPAT_BUILD_FUZZERS}")
751message(STATUS "  Build tests ................ ${EXPAT_BUILD_TESTS}")
752message(STATUS "  Build tools (xmlwf) ........ ${EXPAT_BUILD_TOOLS}")
753message(STATUS "  Build pkg-config file ...... ${EXPAT_BUILD_PKGCONFIG}")
754message(STATUS "  Install files .............. ${EXPAT_ENABLE_INSTALL}")
755message(STATUS "")
756message(STATUS "  Features")
757message(STATUS "    // Advanced options, changes not advised")
758message(STATUS "    Attributes info .......... ${EXPAT_ATTR_INFO}")
759message(STATUS "    Context bytes ............ ${EXPAT_CONTEXT_BYTES}")
760message(STATUS "    DTD support .............. ${EXPAT_DTD}")
761message(STATUS "    Large size ............... ${EXPAT_LARGE_SIZE}")
762message(STATUS "    Minimum size ............. ${EXPAT_MIN_SIZE}")
763message(STATUS "    Namespace support ........ ${EXPAT_NS}")
764message(STATUS "")
765message(STATUS "  Entropy sources")
766if(WIN32)
767    message(STATUS "    rand_s ................... ON")
768else()
769    message(STATUS "    getrandom ................ ${HAVE_GETRANDOM}")
770    message(STATUS "    syscall SYS_getrandom .... ${HAVE_SYSCALL_GETRANDOM}")
771    message(STATUS "    libbsd ................... ${EXPAT_WITH_LIBBSD}")
772    message(STATUS "    /dev/random .............. ${EXPAT_DEV_URANDOM}")
773endif()
774message(STATUS "")
775if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
776    message(STATUS "Continue with")
777    message(STATUS "  make")
778    if(EXPAT_BUILD_TESTS)
779        message(STATUS "  make test")
780    endif()
781    if(EXPAT_ENABLE_INSTALL)
782        message(STATUS "  sudo make install")
783    endif()
784    message(STATUS "")
785endif()
786message(STATUS "===========================================================================")
787