Commit b8aff90997116a84350018f88f1eabdaa368d11b

Authored by Jay Berkenbilt
Committed by Jay Berkenbilt
1 parent 105862da

Add cmake configuration files

CMakeLists.txt 0 → 100644
  1 +# manual/installation.rst mentions the minimum cmake version.
  2 +cmake_minimum_required(VERSION 3.16)
  3 +
  4 +# make_dist expects the version line to be on a line by itself after
  5 +# the project line.
  6 +project(qpdf
  7 + VERSION 10.6.3
  8 + LANGUAGES C CXX)
  9 +
  10 +# Enable correct rpath handling for MacOSX
  11 +cmake_policy(SET CMP0042 NEW)
  12 +# Honor CMAKE_REQUIRED_LIBRARIES when checking for include files
  13 +cmake_policy(SET CMP0075 NEW)
  14 +
  15 +# *** OPTIONS ***
  16 +
  17 +# Keep all options here. It's easier to see the interdependencies this
  18 +# way than spreading them throughout the files.
  19 +#
  20 +# ***** Keep manual/installation.rst (_build-options) up to date. *****
  21 +
  22 +include(CMakeDependentOption)
  23 +
  24 +# CMAKE_DEPENDENT_OPTION(
  25 +# OPTION "Description" default-value-if-visible
  26 +# "when-visible" value-if-not-visible)
  27 +
  28 +# Don't write tests based on MAINTAINER_MODE or CI_MODE. Instead, use
  29 +# them as the basis for dependent options.
  30 +
  31 +option(MAINTAINER_MODE "Set options for developing qpdf" OFF)
  32 +CMAKE_DEPENDENT_OPTION(
  33 + CI_MODE "Set options for running in CI" OFF
  34 + "NOT MAINTAINER_MODE" OFF)
  35 +CMAKE_DEPENDENT_OPTION(
  36 + WERROR "Treat compiler warnings as errors" OFF
  37 + "NOT MAINTAINER_MODE; NOT CI_MODE" ON)
  38 +CMAKE_DEPENDENT_OPTION(
  39 + GENERATE_AUTO_JOB "Automatically regenerate job files" OFF
  40 + "NOT MAINTAINER_MODE" ON)
  41 +CMAKE_DEPENDENT_OPTION(
  42 + SHOW_FAILED_TEST_OUTPUT "Show qtest output on failure" OFF
  43 + "NOT CI_MODE" ON)
  44 +
  45 +# To allow building doc to be disabled in maintainer mode, handle the
  46 +# condition manually rather than using a dependent option.
  47 +if(MAINTAINER_MODE)
  48 + set(default_BUILD_DOC ON)
  49 +else()
  50 + set(default_BUILD_DOC OFF)
  51 +endif()
  52 +option(BUILD_DOC "Build documentation" ${default_BUILD_DOC})
  53 +# The values of BUILD_DOC_HTML and BUILD_DOC_PDF are ignored without
  54 +# BUILD_DOC, so setting them to ON when not visible forces them to be
  55 +# on in MAINTAINER_MODE and is harmless if BUILD_DOC is off.
  56 +CMAKE_DEPENDENT_OPTION(
  57 + BUILD_DOC_HTML "Build HTML documentation"
  58 + ON "BUILD_DOC;NOT MAINTAINER_MODE" ON)
  59 +CMAKE_DEPENDENT_OPTION(
  60 + BUILD_DOC_PDF "Build PDF documentation"
  61 + ON "BUILD_DOC;NOT MAINTAINER_MODE" ON)
  62 +CMAKE_DEPENDENT_OPTION(
  63 + BUILD_DOC_DIST "Create distribution of manual" ON
  64 + "BUILD_DOC_PDF;BUILD_DOC_HTML" OFF)
  65 +
  66 +option(BUILD_SHARED_LIBS "Build qpdf shared libraries" ON)
  67 +option(BUILD_STATIC_LIBS "Build qpdf static libraries" ON)
  68 +option(QTEST_COLOR "Whether qtest's output should be in color" ON)
  69 +option(USE_INSECURE_RANDOM "Use insecure random numbers" OFF)
  70 +option(SKIP_OS_SECURE_RANDOM
  71 + "Suppress use of OS-provided secure random numbers" OFF)
  72 +CMAKE_DEPENDENT_OPTION(
  73 + AVOID_WINDOWS_HANDLE "Avoid use of HANDLE in Windows" OFF
  74 + "WIN32" OFF)
  75 +
  76 +option(OSS_FUZZ "Specific build configuration for the oss-fuzz project" OFF)
  77 +
  78 +option(USE_IMPLICIT_CRYPTO "Enable any available external crypto provider" ON)
  79 +CMAKE_DEPENDENT_OPTION(
  80 + ALLOW_CRYPTO_NATIVE "Allow native crypto as as fallback" ON
  81 + "USE_IMPLICIT_CRYPTO" OFF)
  82 +CMAKE_DEPENDENT_OPTION(
  83 + REQUIRE_CRYPTO_NATIVE "Require native crypto provider" OFF
  84 + "NOT MAINTAINER_MODE; NOT CI_MODE" ON)
  85 +option(REQUIRE_CRYPTO_OPENSSL "Require openssl crypto" OFF)
  86 +option(REQUIRE_CRYPTO_GNUTLS "Require gnutls crypto" OFF)
  87 +set(DEFAULT_CRYPTO CACHE STRING "")
  88 +option(DEFAULT_CRYPTO
  89 + "Specify default crypto; otherwise chosen automatically" "")
  90 +
  91 +# INSTALL_MANUAL is not dependent on building docs. When creating some
  92 +# distributions, we build the doc in one run, copy doc-dist in, and
  93 +# install it elsewhere.
  94 +option(INSTALL_MANUAL "Install documentation" OFF)
  95 +
  96 +option(INSTALL_PKGCONFIG "Install pkgconfig file" ON)
  97 +option(INSTALL_CMAKE_PACKAGE "Install cmake package files" ON)
  98 +option(INSTALL_EXAMPLES "Install example files" ON)
  99 +
  100 +# *** END OPTIONS ***
  101 +
  102 +if(NOT (BUILD_STATIC_LIBS OR BUILD_SHARED_LIBS))
  103 + message(
  104 + FATAL_ERROR "At least one of static or shared libraries must be built")
  105 +endif()
  106 +
  107 +add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:POINTERHOLDER_TRANSITION=2>)
  108 +
  109 +enable_testing()
  110 +set(RUN_QTEST perl ${qpdf_SOURCE_DIR}/run-qtest)
  111 +
  112 +if(WIN32)
  113 + find_program(COPY_COMMAND NAMES cp copy)
  114 + if(COPY_COMMAND STREQUAL "COPY_COMMAND-NOTFOUND")
  115 + set(COPY_COMMAND "copy")
  116 + endif()
  117 +else()
  118 + set(COPY_COMMAND "cp")
  119 +endif()
  120 +
  121 +# For a long time, qpdf used libtool's version system. We are no
  122 +# longer doing that, but to avoid potential conflict with older
  123 +# versions, continue to have the shared library symlink point to a
  124 +# file whose version shares minor and patch with the project version
  125 +# and major with the SOVERSION. Starting with the transition to cmake,
  126 +# increment SOVERSION every time we increment the project major
  127 +# version. This works because qpdf uses semantic versioning. qpdf 10.x
  128 +# was libqpdf28, so start from there.
  129 +math(EXPR qpdf_SOVERSION "${PROJECT_VERSION_MAJOR} + 18")
  130 +set(qpdf_LIBVERSION ${qpdf_SOVERSION}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
  131 +
  132 +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
  133 + message(FATAL_ERROR "
  134 +Please build with cmake in a subdirectory, e.g.
  135 + mkdir build
  136 + cmake ..
  137 + cmake --build .
  138 +Please remove CMakeCache.txt and the CMakeFiles directories.")
  139 +endif()
  140 +
  141 +set(CMAKE_CXX_STANDARD 14)
  142 +set(CMAKE_CXX_EXTENSIONS OFF)
  143 +set(CMAKE_CXX_STANDARD_REQUIRED ON)
  144 +set(CMAKE_C_VISIBILITY_PRESET hidden)
  145 +set(CMAKE_CXX_VISIBILITY_PRESET hidden)
  146 +
  147 +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
  148 +
  149 +if(WIN32 AND NOT SKIP_OS_SECURE_RANDOM)
  150 + list(APPEND CMAKE_REQUIRED_LIBRARIES Advapi32)
  151 +endif()
  152 +
  153 +include(CheckCXXSourceCompiles)
  154 +function(check_atomic)
  155 + foreach(I 0 1)
  156 + if(I)
  157 + set(CMAKE_REQUIRED_LIBRARIES atomic)
  158 + endif()
  159 + check_cxx_source_compiles(
  160 + "#include <atomic>
  161 +int main() {
  162 + static std::atomic<int> a{0};
  163 + a = a.fetch_add(1);
  164 + return 0;
  165 +}"
  166 + ATOMIC_WORKED${I})
  167 + if(ATOMIC_WORKED0)
  168 + return()
  169 + endif()
  170 + endforeach()
  171 + if(ATOMIC_WORKED1)
  172 + list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
  173 + endif()
  174 +endfunction()
  175 +check_atomic()
  176 +
  177 +set(WINDOWS_WMAIN_COMPILE "")
  178 +set(WINDOWS_WMAIN_LINK "")
  179 +if(WIN32)
  180 + function(check_wmain)
  181 + foreach(I 0 1)
  182 + if(NOT WINDOWS_WMAIN_COMPILE)
  183 + if(I)
  184 + set(CMAKE_REQUIRED_LINK_OPTIONS -municode)
  185 + endif()
  186 + check_cxx_source_compiles(
  187 + "#include <windows.h>
  188 +#include <string.h>
  189 +#include <stdio.h>
  190 +extern \"C\"
  191 +int wmain(int argc, wchar_t* argv[])
  192 +{
  193 + size_t x = wcslen(argv[0]);
  194 + return 0;
  195 +}
  196 +"
  197 + WMAIN_WORKED${I})
  198 + endif()
  199 + endforeach()
  200 + if(WMAIN_WORKED1 OR WMAIN_WORKED1)
  201 + set(WINDOWS_WMAIN_COMPILE -DWINDOWS_WMAIN PARENT_SCOPE)
  202 + if(WMAIN_WORKED1 AND NOT WMAIN_WORKED0)
  203 + set(WINDOWS_WMAIN_LINK -municode PARENT_SCOPE)
  204 + endif()
  205 + endif()
  206 + endfunction()
  207 + check_wmain()
  208 +endif()
  209 +
  210 +if(MSVC)
  211 + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS -link setargv.obj)
  212 + list(APPEND WINDOWS_WMAIN_LINK -link wsetargv.obj)
  213 +endif()
  214 +
  215 +include(GNUInstallDirs)
  216 +
  217 +# Compiler flags
  218 +#
  219 +# **NOTE** -- each flag must have its own cache variable.
  220 +
  221 +include(qpdfCheckFlag)
  222 +if(WERROR)
  223 + if(MSVC)
  224 + add_compile_options(/WX)
  225 + else()
  226 + qpdf_maybe_add_flag(C -Werror flag_werror)
  227 + endif()
  228 +endif()
  229 +
  230 +if(MSVC)
  231 + # /Gy combines identical functions -- useful with C++ templates
  232 + add_compile_options(/Gy)
  233 + add_compile_options(/W3) # warning level 3
  234 +else()
  235 + qpdf_maybe_add_flag(C -Wall flag_wall)
  236 + qpdf_maybe_add_flag(C -Wconversion flag_conversion)
  237 + qpdf_maybe_add_flag(C -Wsign-conversion flag_sign-conversion)
  238 + qpdf_maybe_add_flag(C -Wshadow=local flag_shadow_local)
  239 + qpdf_maybe_add_flag(CXX -Wold-style-cast flag_old-style-cast)
  240 +endif()
  241 +
  242 +# We don't include the jpeg library's include path in the PUBLIC
  243 +# interface for libqpdf since only Pl_DCT.hh requires it. This is
  244 +# documented. Some examples and tests use it though so we have to
  245 +# define it. CMakeLists.txt for libqpdf sets the value for
  246 +# JPEG_INCLUDE which can be selectively added to include paths other
  247 +# tools.
  248 +set(JPEG_INCLUDE)
  249 +
  250 +if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
  251 + set(WORDSIZE 64)
  252 +else()
  253 + set(WORDSIZE 32)
  254 +endif()
  255 +if(MSVC)
  256 + set(CPACK_SYSTEM_NAME "msvc${WORDSIZE}")
  257 +elseif(MINGW)
  258 + set(CPACK_SYSTEM_NAME "mingw${WORDSIZE}")
  259 +endif()
  260 +set(CPACK_RESOURCE_FILE_LICENSE "${qpdf_SOURCE_DIR}/LICENSE.txt")
  261 +set(CPACK_PACKAGE_HOMEPAGE_URL "https://qpdf.sourceforge.io/")
  262 +set(CPACK_NSIS_MUI_ICON "${qpdf_SOURCE_DIR}/logo/qpdf.ico")
  263 +
  264 +include(CPack)
  265 +
  266 +# Install components -- documented in _installation in
  267 +# manual/installation.rst.
  268 +set(COMPONENT_DEV "dev")
  269 +set(COMPONENT_LIB "lib") # runtime library
  270 +set(COMPONENT_CLI "cli")
  271 +set(COMPONENT_DOC "doc")
  272 +set(COMPONENT_EXAMPLES "examples") # example sources
  273 +
  274 +if(WIN32)
  275 + include(InstallRequiredSystemLibraries)
  276 +endif()
  277 +
  278 +# add_subdirectory order affects test order
  279 +add_subdirectory(include)
  280 +add_subdirectory(libqpdf)
  281 +add_subdirectory(qpdf)
  282 +add_subdirectory(libtests)
  283 +add_subdirectory(examples)
  284 +add_subdirectory(zlib-flate)
  285 +add_subdirectory(manual)
  286 +add_subdirectory(fuzz)
  287 +
  288 +# We don't need to show everything -- just the things that we really
  289 +# need to be sure are right or that are turned on or off with complex
  290 +# logic.
  291 +get_property(MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  292 +message(STATUS "")
  293 +message(STATUS "*** Summary ***")
  294 +message(STATUS " qpdf version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
  295 +if(MULTI_CONFIG)
  296 + message(STATUS " build type: specify --config at build time")
  297 +elseif(CMAKE_BUILD_TYPE)
  298 + message(STATUS " build type: ${CMAKE_BUILD_TYPE}")
  299 +endif()
  300 +message(STATUS " build shared libraries: ${BUILD_SHARED_LIBS}")
  301 +message(STATUS " build static libraries: ${BUILD_STATIC_LIBS}")
  302 +message(STATUS " build manual: ${BUILD_DOC}")
  303 +message(STATUS " compiler warnings are errors: ${WERROR}")
  304 +message(STATUS " system: ${CPACK_SYSTEM_NAME}")
  305 +message(STATUS "")
  306 +message(STATUS "*** Options Summary ***")
  307 +foreach(PROP
  308 + COMPILE_OPTIONS INTERFACE_COMPILE_OPTIONS
  309 + COMPILE_DEFINITIONS INTERFACE_COMPILE_DEFINITIONS
  310 + INCLUDE_DIRECTORIES INTERFACE_INCLUDE_DIRECTORIES
  311 + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
  312 + LINK_OPTIONS INTERFACE_LINK_OPTIONS
  313 + LINK_LIBRARIES INTERFACE_LINK_LIBRARIES
  314 + LINK_DIRECTORIES INTERFACE_LINK_DIRECTORIES)
  315 + get_target_property(VAL libqpdf ${PROP})
  316 + if(NOT (VAL STREQUAL "VAL-NOTFOUND"))
  317 + message(STATUS " ${PROP}: ${VAL}")
  318 + endif()
  319 +endforeach()
  320 +if(APPLE)
  321 + message(STATUS " CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}")
  322 +endif()
  323 +message(STATUS "")
  324 +message(STATUS "See above for crypto summary.")
  325 +message(STATUS "")
  326 +if(NOT (MULTI_CONFIG OR CMAKE_BUILD_TYPE))
  327 + message(WARNING " CMAKE_BUILD_TYPE is not set; using default settings")
  328 +endif()
... ...
cmake/qpdfCheckFlag.cmake 0 → 100644
  1 +include(CheckCXXCompilerFlag)
  2 +include(CheckCCompilerFlag)
  3 +
  4 +function(qpdf_maybe_add_flag lang flag var)
  5 + if(${lang} STREQUAL "C")
  6 + check_c_compiler_flag(${flag} ${var})
  7 + elseif(${lang} STREQUAL "CXX")
  8 + check_cxx_compiler_flag(${flag} ${var})
  9 + endif()
  10 + if(${var})
  11 + message(STATUS "Using ${flag}: YES")
  12 + if(${lang} STREQUAL "C")
  13 + # Add for C and C++
  14 + add_compile_options(${flag})
  15 + else()
  16 + add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${flag}>)
  17 + endif()
  18 + else()
  19 + message(STATUS "Using ${flag}: NO")
  20 + endif()
  21 +endfunction()
... ...
examples/CMakeLists.txt 0 → 100644
  1 +set(EXAMPLE_CXX_PROGRAMS
  2 + pdf-attach-file
  3 + pdf-bookmarks
  4 + pdf-count-strings
  5 + pdf-create
  6 + pdf-custom-filter
  7 + pdf-double-page-size
  8 + pdf-filter-tokens
  9 + pdf-invert-images
  10 + pdf-mod-info
  11 + pdf-name-number-tree
  12 + pdf-npages
  13 + pdf-overlay-page
  14 + pdf-parse-content
  15 + pdf-set-form-values
  16 + pdf-split-pages
  17 + qpdf-job)
  18 +set(EXAMPLE_C_PROGRAMS
  19 + pdf-c-objects
  20 + pdf-linearize
  21 + qpdfjob-c)
  22 +
  23 +foreach(PROG ${EXAMPLE_CXX_PROGRAMS})
  24 + add_executable(${PROG} ${PROG}.cc)
  25 + target_link_libraries(${PROG} libqpdf)
  26 +endforeach()
  27 +foreach(PROG ${EXAMPLE_C_PROGRAMS})
  28 + add_executable(${PROG} ${PROG}.c)
  29 + target_link_libraries(${PROG} libqpdf)
  30 + set_property(TARGET ${PROG} PROPERTY LINKER_LANGUAGE CXX)
  31 +endforeach()
  32 +target_include_directories(pdf-create PRIVATE ${JPEG_INCLUDE})
  33 +
  34 +add_test(
  35 + NAME examples
  36 + COMMAND ${RUN_QTEST}
  37 + --top ${qpdf_SOURCE_DIR}
  38 + --bin $<TARGET_FILE_DIR:pdf-create>
  39 + --bin $<TARGET_FILE_DIR:qpdf>
  40 + --bin $<TARGET_FILE_DIR:libqpdf> # for Windows to find DLL
  41 + --code ${qpdf_SOURCE_DIR}/examples
  42 + --color ${QTEST_COLOR}
  43 + --show-on-failure ${SHOW_FAILED_TEST_OUTPUT}
  44 + --tc "${qpdf_SOURCE_DIR}/examples/*.cc"
  45 + --tc "${qpdf_SOURCE_DIR}/examples/*.c")
  46 +
  47 +file(GLOB EXAMPLES_SRC "*.c" "*.cc")
  48 +if(INSTALL_EXAMPLES)
  49 + install(FILES ${EXAMPLES_SRC}
  50 + DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples
  51 + COMPONENT ${COMPONENT_EXAMPLES})
  52 +endif()
... ...
fuzz/CMakeLists.txt 0 → 100644
  1 +# This directory contains support for Google's oss-fuzz project. See
  2 +# https://github.com/google/oss-fuzz/tree/master/projects/qpdf
  3 +
  4 +set(FUZZERS
  5 + qpdf_fuzzer
  6 + ascii85_fuzzer
  7 + dct_fuzzer
  8 + flate_fuzzer
  9 + hex_fuzzer
  10 + lzw_fuzzer
  11 + pngpredictor_fuzzer
  12 + runlength_fuzzer
  13 + tiffpredictor_fuzzer)
  14 +
  15 +# The oss-fuzz project provides LIB_FUZZING_ENGINE and OUT environment
  16 +# variables. For local testing, provide values if not set.
  17 +set(LIB_FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE})
  18 +if(NOT LIB_FUZZING_ENGINE)
  19 + # When running from oss-fuzz, LIB_FUZZING_ENGINE points to a
  20 + # static library that contains main.
  21 + add_library(standalone_fuzzer STATIC standalone_fuzz_target_runner.cc)
  22 + target_include_directories(
  23 + standalone_fuzzer PRIVATE ${qpdf_SOURCE_DIR}/include)
  24 + set(LIB_FUZZING_ENGINE standalone_fuzzer)
  25 +endif()
  26 +set(FUZZ_OUT $ENV{OUT})
  27 +if(NOT FUZZ_OUT)
  28 + set(FUZZ_OUT ${CMAKE_CURRENT_BINARY_DIR}/fuzz-install)
  29 +endif()
  30 +
  31 +if(OSS_FUZZ)
  32 + # We need to link jpeg and zlib statically for oss-fuzz. Construct
  33 + # our own object library without the external dependencies and add
  34 + # what we need.
  35 + add_library(libqpdf_fuzz STATIC $<TARGET_OBJECTS:libqpdf_object>)
  36 + target_link_libraries(libqpdf_fuzz INTERFACE libjpeg.a libz.a)
  37 + target_include_directories(libqpdf_fuzz
  38 + PUBLIC
  39 + ${JPEG_INCLUDE}
  40 + ${qpdf_SOURCE_DIR}/include
  41 + ${qpdf_SOURCE_DIR}/libqpdf)
  42 +else()
  43 + add_library(libqpdf_fuzz ALIAS libqpdf_object)
  44 +endif()
  45 +
  46 +foreach(PROG ${FUZZERS})
  47 + add_executable(${PROG} ${PROG}.cc)
  48 + target_link_libraries(${PROG} ${LIB_FUZZING_ENGINE})
  49 + target_link_libraries(${PROG} libqpdf_fuzz)
  50 +endforeach()
  51 +
  52 +# Files from the test suite that are good for seeding the fuzzer.
  53 +# Update count for qpdf in @fuzzers qtest/fuzz.test if you change this list.
  54 +set(CORPUS_FROM_TEST
  55 + stream-data.pdf
  56 + lin5.pdf
  57 + field-types.pdf
  58 + image-streams-small.pdf
  59 + need-appearances.pdf
  60 + outlines-with-actions.pdf
  61 + outlines-with-old-root-dests.pdf
  62 + page-labels-and-outlines.pdf
  63 + page-labels-num-tree.pdf
  64 + dr-with-indirect-item.pdf
  65 + fuzz-16214.pdf
  66 + issue-99b.pdf
  67 + issue-99.pdf
  68 + issue-100.pdf
  69 + issue-101.pdf
  70 + issue-106.pdf
  71 + issue-117.pdf
  72 + issue-119.pdf
  73 + issue-120.pdf
  74 + issue-141a.pdf
  75 + issue-141b.pdf
  76 + issue-143.pdf
  77 + issue-146.pdf
  78 + issue-147.pdf
  79 + issue-148.pdf
  80 + issue-149.pdf
  81 + issue-150.pdf
  82 + issue-202.pdf
  83 + issue-263.pdf
  84 + issue-335a.pdf
  85 + issue-335b.pdf)
  86 +
  87 +# Any file that qpdf_fuzzer should be tested with can be named
  88 +# something.fuzz and dropped into qpdf_extra. Update count for qpdf in
  89 +# @fuzzers qtest/fuzz.test if you change this list.
  90 +set(CORPUS_OTHER
  91 + 15316.fuzz
  92 + 15387.fuzz
  93 + 15390.fuzz
  94 + 15442.fuzz
  95 + 15445.fuzz
  96 + 15983.fuzz
  97 + 16172.fuzz
  98 + 16301.fuzz
  99 + 16953.fuzz
  100 + 18241.fuzz
  101 + 18247.fuzz
  102 + 23172.fuzz
  103 + 23599.fuzz
  104 + 23642.fuzz
  105 + 23642-mod.fuzz
  106 + 26761.fuzz
  107 + 26994.fuzz
  108 + 27393.fuzz
  109 + 28262.fuzz
  110 + 30507.fuzz
  111 + 37740.fuzz)
  112 +
  113 +set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus)
  114 +file(MAKE_DIRECTORY ${CORPUS_DIR})
  115 +function(copy_fuzz FROM)
  116 + file(SHA1 ${FROM} SHA)
  117 + set(OUT ${CORPUS_DIR}/${SHA})
  118 + add_custom_command(
  119 + OUTPUT ${OUT}
  120 + COMMAND ${COPY_COMMAND} $<SHELL_PATH:${FROM}> $<SHELL_PATH:${OUT}>)
  121 + set(CORPUS_FILE ${OUT} PARENT_SCOPE)
  122 +endfunction()
  123 +
  124 +list(APPEND CORPUS_FILES)
  125 +foreach(F ${CORPUS_FROM_TEST})
  126 + copy_fuzz(${qpdf_SOURCE_DIR}/qpdf/qtest/qpdf/${F})
  127 + list(APPEND CORPUS_FILES ${CORPUS_FILE})
  128 +endforeach()
  129 +foreach(F ${CORPUS_OTHER})
  130 + copy_fuzz(${CMAKE_CURRENT_SOURCE_DIR}/qpdf_extra/${F})
  131 + list(APPEND CORPUS_FILES ${CORPUS_FILE})
  132 +endforeach()
  133 +add_custom_target(qpdf_corpus ALL
  134 + DEPENDS ${CORPUS_FILES})
  135 +
  136 +add_test(
  137 + NAME fuzz
  138 + COMMAND ${RUN_QTEST}
  139 + --env QPDF_FUZZ_CORPUS=${CORPUS_DIR}
  140 + --top ${qpdf_SOURCE_DIR}
  141 + --bin $<TARGET_FILE_DIR:qpdf_fuzzer>
  142 + --bin $<TARGET_FILE_DIR:qpdf>
  143 + --code ${qpdf_SOURCE_DIR}/fuzz
  144 + --color ${QTEST_COLOR}
  145 + --show-on-failure ${SHOW_FAILED_TEST_OUTPUT})
  146 +
  147 +if(OSS_FUZZ)
  148 + list(APPEND SEED_CORPUS_ZIPS)
  149 + foreach(F ${FUZZERS})
  150 + if(F STREQUAL qpdf_fuzzer)
  151 + set(SEED_DIR ${CORPUS_DIR})
  152 + else()
  153 + set(SEED_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${F}_seed_corpus)
  154 + endif()
  155 + set(SEED_ZIP ${CMAKE_CURRENT_BINARY_DIR}/${F}_seed_corpus.zip)
  156 + add_custom_command(OUTPUT ${SEED_ZIP}
  157 + COMMAND zip -q -r ${SEED_ZIP} .
  158 + WORKING_DIRECTORY ${SEED_DIR})
  159 + list(APPEND SEED_CORPUS_ZIPS ${SEED_ZIP})
  160 + endforeach()
  161 + add_custom_target(seed_corpus_zips ALL DEPENDS ${SEED_CORPUS_ZIPS})
  162 + add_dependencies(seed_corpus_zips qpdf_corpus)
  163 + add_custom_target(fuzzers)
  164 + add_dependencies(fuzzers ${FUZZERS} seed_corpus_zips)
  165 + install(
  166 + TARGETS ${FUZZERS}
  167 + DESTINATION ${FUZZ_OUT}
  168 + EXCLUDE_FROM_ALL
  169 + COMPONENT fuzz)
  170 + install(
  171 + FILES
  172 + ${CMAKE_CURRENT_SOURCE_DIR}/pdf.dict
  173 + ${CMAKE_CURRENT_SOURCE_DIR}/qpdf_fuzzer.options
  174 + ${SEED_CORPUS_ZIPS}
  175 + DESTINATION ${FUZZ_OUT}
  176 + EXCLUDE_FROM_ALL
  177 + COMPONENT fuzz)
  178 +endif()
... ...
include/CMakeLists.txt 0 → 100644
  1 +set(qpdf_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
  2 +
  3 +# While globs are not considered best practice, it makes sense for
  4 +# installation o header files. When compiling, you specify an entire
  5 +# directory, so not doing the same at installation time creates a high
  6 +# risk that forgetting to explicitly add a header to an installation
  7 +# list would not be detected in CI or at any time until an end user
  8 +# tries to build code.
  9 +install(DIRECTORY qpdf
  10 + TYPE INCLUDE
  11 + COMPONENT ${COMPONENT_DEV}
  12 + FILES_MATCHING PATTERN "*.h" PATTERN "*.hh")
... ...
libqpdf/CMakeLists.txt 0 → 100644
  1 +
  2 +if(GENERATE_AUTO_JOB)
  3 + execute_process(
  4 + COMMAND ${qpdf_SOURCE_DIR}/generate_auto_job --generate
  5 + WORKING_DIRECTORY ${qpdf_SOURCE_DIR})
  6 +endif()
  7 +
  8 +set(libqpdf_crypto_native
  9 + AES_PDF_native.cc
  10 + MD5_native.cc
  11 + QPDFCrypto_native.cc
  12 + RC4_native.cc
  13 + SHA2_native.cc
  14 + rijndael.cc
  15 + sha2.c
  16 + sha2big.c)
  17 +
  18 +set(libqpdf_crypto_openssl
  19 + QPDFCrypto_openssl.cc)
  20 +
  21 +set(libqpdf_crypto_gnutls
  22 + QPDFCrypto_gnutls.cc)
  23 +
  24 +set(libqpdf_SOURCES
  25 + BitStream.cc
  26 + BitWriter.cc
  27 + Buffer.cc
  28 + BufferInputSource.cc
  29 + ClosedFileInputSource.cc
  30 + ContentNormalizer.cc
  31 + CryptoRandomDataProvider.cc
  32 + FileInputSource.cc
  33 + InputSource.cc
  34 + InsecureRandomDataProvider.cc
  35 + JSON.cc
  36 + JSONHandler.cc
  37 + MD5.cc
  38 + NNTree.cc
  39 + OffsetInputSource.cc
  40 + PDFVersion.cc
  41 + Pipeline.cc
  42 + Pl_AES_PDF.cc
  43 + Pl_ASCII85Decoder.cc
  44 + Pl_ASCIIHexDecoder.cc
  45 + Pl_Buffer.cc
  46 + Pl_Concatenate.cc
  47 + Pl_Count.cc
  48 + Pl_DCT.cc
  49 + Pl_Discard.cc
  50 + Pl_Flate.cc
  51 + Pl_LZWDecoder.cc
  52 + Pl_MD5.cc
  53 + Pl_PNGFilter.cc
  54 + Pl_QPDFTokenizer.cc
  55 + Pl_RC4.cc
  56 + Pl_RunLength.cc
  57 + Pl_SHA2.cc
  58 + Pl_StdioFile.cc
  59 + Pl_TIFFPredictor.cc
  60 + QPDF.cc
  61 + QPDFAcroFormDocumentHelper.cc
  62 + QPDFAnnotationObjectHelper.cc
  63 + QPDFArgParser.cc
  64 + QPDFCryptoProvider.cc
  65 + QPDFEFStreamObjectHelper.cc
  66 + QPDFEmbeddedFileDocumentHelper.cc
  67 + QPDFExc.cc
  68 + QPDFFileSpecObjectHelper.cc
  69 + QPDFFormFieldObjectHelper.cc
  70 + QPDFJob.cc
  71 + QPDFJob_argv.cc
  72 + QPDFJob_config.cc
  73 + QPDFJob_json.cc
  74 + QPDFMatrix.cc
  75 + QPDFNameTreeObjectHelper.cc
  76 + QPDFNumberTreeObjectHelper.cc
  77 + QPDFObjGen.cc
  78 + QPDFObject.cc
  79 + QPDFObjectHandle.cc
  80 + QPDFOutlineDocumentHelper.cc
  81 + QPDFOutlineObjectHelper.cc
  82 + QPDFPageDocumentHelper.cc
  83 + QPDFPageLabelDocumentHelper.cc
  84 + QPDFPageObjectHelper.cc
  85 + QPDFStreamFilter.cc
  86 + QPDFSystemError.cc
  87 + QPDFTokenizer.cc
  88 + QPDFUsage.cc
  89 + QPDFWriter.cc
  90 + QPDFXRefEntry.cc
  91 + QPDF_Array.cc
  92 + QPDF_Bool.cc
  93 + QPDF_Dictionary.cc
  94 + QPDF_InlineImage.cc
  95 + QPDF_Integer.cc
  96 + QPDF_Name.cc
  97 + QPDF_Null.cc
  98 + QPDF_Operator.cc
  99 + QPDF_Real.cc
  100 + QPDF_Reserved.cc
  101 + QPDF_Stream.cc
  102 + QPDF_String.cc
  103 + QPDF_encryption.cc
  104 + QPDF_linearization.cc
  105 + QPDF_optimization.cc
  106 + QPDF_pages.cc
  107 + QTC.cc
  108 + QUtil.cc
  109 + RC4.cc
  110 + ResourceFinder.cc
  111 + SecureRandomDataProvider.cc
  112 + SF_FlateLzwDecode.cc
  113 + SparseOHArray.cc
  114 + qpdf-c.cc
  115 + qpdfjob-c.cc)
  116 +
  117 +include(FindPkgConfig)
  118 +include(CheckTypeSize)
  119 +include(CheckIncludeFile)
  120 +include(CheckCSourceCompiles)
  121 +include(CheckCSourceRuns)
  122 +include(CheckSymbolExists)
  123 +
  124 +set(dep_include_directories)
  125 +set(dep_link_directories)
  126 +set(dep_link_libraries)
  127 +set(ANYTHING_MISSING 0)
  128 +
  129 +if(WIN32 AND (EXISTS ${qpdf_SOURCE_DIR}/external-libs))
  130 + set(EXTERNAL_LIBS 1)
  131 +else()
  132 + set(EXTERNAL_LIBS 0)
  133 +endif()
  134 +
  135 +if(EXTERNAL_LIBS)
  136 + set(EXTLIBDIR ${qpdf_SOURCE_DIR}/external-libs)
  137 + list(APPEND dep_include_directories ${EXTLIBDIR}/include)
  138 + set(JPEG_INCLUDE ${EXTLIBDIR}/include)
  139 + list(APPEND dep_link_libraries
  140 + z jpeg ssl crypto msvcrt ws2_32 shell32 advapi32 gdi32 user32 crypt32)
  141 + if (MSVC)
  142 + list(APPEND dep_link_directories ${EXTLIBDIR}/lib-msvc${WORDSIZE})
  143 + else()
  144 + list(APPEND dep_link_directories ${EXTLIBDIR}/lib-mingw${WORDSIZE})
  145 + endif()
  146 +endif()
  147 +
  148 +if(NOT EXTERNAL_LIBS)
  149 + pkg_check_modules(pc_zlib zlib)
  150 + if(pc_zlib_FOUND)
  151 + list(APPEND dep_include_directories ${pc_zlib_INCLUDEDIR})
  152 + list(APPEND dep_link_directories ${pc_zlib_LIBDIR})
  153 + list(APPEND dep_link_libraries ${pc_zlib_LIBRARIES})
  154 + else()
  155 + find_path(ZLIB_H_PATH zlib.h)
  156 + find_library(ZLIB_LIB_PATH z zlib)
  157 + if(ZLIB_H_PATH AND ZLIB_LIB_PATH)
  158 + list(APPEND dep_include_directories ${ZLIB_H_PATH})
  159 + list(APPEND dep_link_libraries ${ZLIB_LIB_PATH})
  160 + else()
  161 + message(SEND_ERROR "zlib not found")
  162 + set(ANYTHING_MISSING 1)
  163 + endif()
  164 + endif()
  165 +endif()
  166 +
  167 +if(NOT EXTERNAL_LIBS)
  168 + pkg_check_modules(pc_libjpeg libjpeg)
  169 + if(pc_libjpeg_FOUND)
  170 + list(APPEND dep_include_directories ${pc_libjpeg_INCLUDEDIR})
  171 + list(APPEND dep_link_directories ${pc_libjpeg_LIBDIR})
  172 + list(APPEND dep_link_libraries ${pc_libjpeg_LIBRARIES})
  173 + set(JPEG_INCLUDE ${pc_libjpeg_INCLUDEDIR})
  174 + else()
  175 + find_path(LIBJPEG_H_PATH jpeglib.h)
  176 + find_library(LIBJPEG_LIB_PATH jpeg)
  177 + if(LIBJPEG_H_PATH AND LIBJPEG_LIB_PATH)
  178 + list(APPEND dep_include_directories ${LIBJPEG_H_PATH})
  179 + list(APPEND dep_link_libraries ${LIBJPEG_LIB_PATH})
  180 + set(JPEG_INCLUDE ${LIBJPEG_H_PATH})
  181 + else()
  182 + message(SEND_ERROR "libjpeg not found")
  183 + set(ANYTHING_MISSING 1)
  184 + endif()
  185 + endif()
  186 +endif()
  187 +
  188 +# Update JPEG_INCLUDE in PARENT_SCOPE after we have finished setting it.
  189 +set(JPEG_INCLUDE ${JPEG_INCLUDE} PARENT_SCOPE)
  190 +
  191 +# Crypto provider selection. Prefer external crypto providers. If
  192 +# implicit selection is allowed, use native only when no other options
  193 +# are available or when explicitly requested. Allowing native as a
  194 +# fallback can be disabled using the ALLOW_CRYPTO_NATIVE option.
  195 +list(APPEND CRYPTO_PKG)
  196 +
  197 +set(USE_CRYPTO_GNUTLS OFF)
  198 +set(USE_CRYPTO_OPENSSL OFF)
  199 +set(USE_CRYPTO_NATIVE OFF)
  200 +set(FOUND_CRYPTO OFF)
  201 +
  202 +if(USE_IMPLICIT_CRYPTO OR REQUIRE_CRYPTO_OPENSSL)
  203 + if(EXTERNAL_LIBS)
  204 + set(USE_CRYPTO_OPENSSL ON)
  205 + else()
  206 + pkg_check_modules(pc_openssl openssl>=1.1.0)
  207 + if(pc_openssl_FOUND)
  208 + set(USE_CRYPTO_OPENSSL ON)
  209 + set(FOUND_CRYPTO ON)
  210 + set(CRYPTO_PKG "${CRYPTO_PKG}, openssl>=1.1.0")
  211 + else()
  212 + find_path(OPENSSL_H_PATH openssl/evp.h)
  213 + find_library(OPENSSL_LIB_PATH crypto)
  214 + if(OPENSSL_H_PATH AND OPENSSL_LIB_PATH)
  215 + list(APPEND dep_include_directories ${OPENSSL_H_PATH})
  216 + list(APPEND dep_link_libraries ${OPENSSL_LIB_PATH})
  217 + set(USE_CRYPTO_OPENSSL ON)
  218 + set(FOUND_CRYPTO ON)
  219 + elseif(REQUIRE_CRYPTO_OPENSSL)
  220 + message(SEND_ERROR "openssl not found")
  221 + set(ANYTHING_MISSING 1)
  222 + endif()
  223 + endif()
  224 + endif()
  225 +endif()
  226 +if(USE_IMPLICIT_CRYPTO OR REQUIRE_CRYPTO_GNUTLS)
  227 + pkg_check_modules(pc_gnutls gnutls)
  228 + if(pc_gnutls_FOUND)
  229 + set(USE_CRYPTO_GNUTLS ON)
  230 + set(FOUND_CRYPTO ON)
  231 + set(CRYPTO_PKG "${CRYPTO_PKG}, gnutls")
  232 + else()
  233 + find_path(GNUTLS_H_PATH gnutls/gnutls.h)
  234 + find_library(GNUTLS_LIB_PATH gnutls)
  235 + if(GNUTLS_H_PATH AND GNUTLS_LIB_PATH)
  236 + list(APPEND dep_include_directories ${GNUTLS_H_PATH})
  237 + list(APPEND dep_link_libraries ${GNUTLS_LIB_PATH})
  238 + set(USE_CRYPTO_GNUTLS ON)
  239 + set(FOUND_CRYPTO ON)
  240 + elseif(REQUIRE_CRYPTO_GNUTLS)
  241 + message(SEND_ERROR "gnutls not found")
  242 + set(ANYTHING_MISSING 1)
  243 + endif()
  244 + endif()
  245 +endif()
  246 +if(REQUIRE_CRYPTO_NATIVE)
  247 + set(USE_CRYPTO_NATIVE ON)
  248 + set(FOUND_CRYPTO ON)
  249 +elseif(USE_IMPLICIT_CRYPTO)
  250 + if(ALLOW_CRYPTO_NATIVE AND (NOT FOUND_CRYPTO))
  251 + set(USE_CRYPTO_NATIVE ON)
  252 + set(FOUND_CRYPTO ON)
  253 + endif()
  254 +endif()
  255 +if(FOUND_CRYPTO)
  256 + if(NOT DEFAULT_CRYPTO)
  257 + # The preferred order of crypto providers is documented in
  258 + # manual/installation.rst in the crypto.build section.
  259 + if(USE_CRYPTO_GNUTLS)
  260 + set(DEFAULT_CRYPTO "gnutls")
  261 + elseif(USE_CRYPTO_OPENSSL)
  262 + set(DEFAULT_CRYPTO "openssl")
  263 + else()
  264 + set(DEFAULT_CRYPTO "native")
  265 + endif()
  266 + endif()
  267 +else()
  268 + message(SEND_ERROR "no crypto provider is available")
  269 + set(ANYTHING_MISSING 1)
  270 +endif()
  271 +if(ANYTHING_MISSING)
  272 + message(FATAL_ERROR "Missing dependencies; unable to continue")
  273 +endif()
  274 +
  275 +message(STATUS "")
  276 +message(STATUS "*** Crypto Summary ***")
  277 +message(STATUS " GNU TLS crypto enabled: " ${USE_CRYPTO_GNUTLS})
  278 +message(STATUS " OpenSSL crypto enabled: " ${USE_CRYPTO_OPENSSL})
  279 +message(STATUS " Native crypto enabled: " ${USE_CRYPTO_NATIVE})
  280 +message(STATUS " Default crypto: " ${DEFAULT_CRYPTO})
  281 +message(STATUS "")
  282 +
  283 +if(USE_CRYPTO_OPENSSL)
  284 + list(APPEND libqpdf_SOURCES ${libqpdf_crypto_openssl})
  285 + if(NOT EXTERNAL_LIBS)
  286 + list(APPEND dep_include_directories ${pc_openssl_INCLUDEDIR})
  287 + list(APPEND dep_link_directories ${pc_openssl_LIBDIR})
  288 + list(APPEND dep_link_libraries ${pc_openssl_LIBRARIES})
  289 + endif()
  290 +endif()
  291 +if(USE_CRYPTO_GNUTLS)
  292 + list(APPEND libqpdf_SOURCES ${libqpdf_crypto_gnutls})
  293 + list(APPEND dep_include_directories ${pc_gnutls_INCLUDEDIR})
  294 + list(APPEND dep_link_directories ${pc_gnutls_LIBDIR})
  295 + list(APPEND dep_link_libraries ${pc_gnutls_LIBRARIES})
  296 +endif()
  297 +if(USE_CRYPTO_NATIVE)
  298 + list(APPEND libqpdf_SOURCES ${libqpdf_crypto_native})
  299 +endif()
  300 +
  301 +if(APPLE)
  302 + # 2022: in CI (GitHub actions), pkg-config for zlib was adding a
  303 + # broken directory to the include path. This effectively filters it
  304 + # out.
  305 + list(FILTER dep_include_directories EXCLUDE REGEX "^/Library/")
  306 +endif()
  307 +
  308 +list(REMOVE_DUPLICATES dep_include_directories)
  309 +list(REMOVE_DUPLICATES dep_link_directories)
  310 +list(REMOVE_DUPLICATES dep_link_libraries)
  311 +
  312 +check_type_size(size_t SIZEOF_SIZE_T)
  313 +check_include_file("inttypes.h" HAVE_INTTYPES_H)
  314 +check_symbol_exists(fseeko "stdio.h" HAVE_FSEEKO)
  315 +check_symbol_exists(fseeko64 "stdio.h" HAVE_FSEEKO64)
  316 +check_symbol_exists(localtime_r "time.h" HAVE_LOCALTIME_R)
  317 +check_symbol_exists(random "stdlib.h" HAVE_RANDOM)
  318 +find_file(RANDOM_DEVICE
  319 + "urandom" "arandom" "arandom" PATHS "/dev" NO_DEFAULT_PATH)
  320 +
  321 +check_c_source_compiles(
  322 +"#include <time.h>
  323 +#include <stdio.h>
  324 +int main(int argc, char* argv[]) {
  325 + tzset();
  326 + printf(\"%ld\", timezone);
  327 + return 0;
  328 +}"
  329 + HAVE_EXTERN_LONG_TIMEZONE)
  330 +
  331 +check_c_source_compiles(
  332 +"#include <time.h>
  333 +int main(int argc, char* argv[]) {
  334 + struct tm tm;
  335 + tm.tm_gmtoff = 1;
  336 + return 0;
  337 +}"
  338 + HAVE_EXTERN_TM_GMTOFF)
  339 +
  340 +check_c_source_compiles(
  341 +"#include <stdio.h>
  342 +#include <sys/types.h>
  343 +int main(int argc, char* argv[]) {
  344 + int a[sizeof(off_t) >= 8 ? 1 : -1];
  345 +}"
  346 + LFS_WITHOUT_MACROS)
  347 +
  348 +check_c_source_compiles(
  349 +"#define _FILE_OFFSET_BITS 64
  350 +#include <stdio.h>
  351 +#include <sys/types.h>
  352 +int main(int argc, char* argv[]) {
  353 + int a[sizeof(off_t) >= 8 ? 1 : -1];
  354 +}"
  355 + LFS_WITH_MACROS)
  356 +if(LFS_WITH_MACROS AND NOT LFS_WITHOUT_MACROS)
  357 + set(_FILE_OFFSET_BITS 64)
  358 +endif()
  359 +
  360 +function(qpdf_check_ll_fmt fmt var)
  361 + if(NOT DEFINED LL_FMT)
  362 + check_c_source_runs(
  363 + "#define _CRT_SECURE_NO_WARNINGS
  364 +#include <stdio.h>
  365 +#include <string.h>
  366 +int main(int argc, char* argv[]) {
  367 + long long int a = 123456789012345ll;
  368 + char s[30];
  369 + sprintf(s, \"${fmt}\", a);
  370 + return (strcmp(s, \"123456789012345\") == 0) ? 0 : 1;
  371 +}" ${var})
  372 + if(${var})
  373 + set(LL_FMT "${fmt}" PARENT_SCOPE)
  374 + endif()
  375 + endif()
  376 +endfunction()
  377 +
  378 +qpdf_check_ll_fmt("%lld" fmt_lld)
  379 +qpdf_check_ll_fmt("%I64d" fmt_i64d)
  380 +qpdf_check_ll_fmt("%I64lld" fmt_i64lld)
  381 +
  382 +configure_file(
  383 + "${CMAKE_CURRENT_SOURCE_DIR}/qpdf/qpdf-config.h.in"
  384 + "${CMAKE_CURRENT_BINARY_DIR}/qpdf/qpdf-config.h"
  385 + NEWLINE_STYLE UNIX)
  386 +
  387 +if(NOT BUILD_STATIC_LIBS)
  388 + set(OBJECT_LIB_IS_PIC ON)
  389 +else()
  390 + set(OBJECT_LIB_IS_PIC OFF)
  391 +endif()
  392 +
  393 +# Build an "object library" for use in libtests so we don't have to
  394 +# export symbols that are not officially part of the public API. If we
  395 +# are building static libraries, the object library won't use
  396 +# position-independent code and will provided objects for the static
  397 +# library. If we are only building the shared library, go ahead and
  398 +# use PIC for the object library so we don't have to compile twice.
  399 +set(OBJECT_LIB libqpdf_object)
  400 +add_library(${OBJECT_LIB} OBJECT ${libqpdf_SOURCES})
  401 +set_target_properties(${OBJECT_LIB} PROPERTIES
  402 + POSITION_INDEPENDENT_CODE ${OBJECT_LIB_IS_PIC})
  403 +target_include_directories(${OBJECT_LIB}
  404 + SYSTEM PRIVATE ${dep_include_directories})
  405 +target_include_directories(${OBJECT_LIB}
  406 + PUBLIC
  407 + ${JPEG_INCLUDE}
  408 + ${qpdf_INCLUDE}
  409 + ${qpdf_SOURCE_DIR}/libqpdf
  410 + ${CMAKE_CURRENT_BINARY_DIR})
  411 +target_link_directories(${OBJECT_LIB} INTERFACE ${dep_link_directories})
  412 +target_link_libraries(${OBJECT_LIB} INTERFACE ${dep_link_libraries})
  413 +
  414 +set(LD_VERSION_FLAGS "")
  415 +function(ld_version_script)
  416 + # Check if the linker supports linker scripts, and use if it does.
  417 + # This functionality is currently constrained to compilers using GNU
  418 + # ld on ELF systems or systems that emulation this behavior.
  419 + set(ld_script
  420 + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/qpdf-tmp/conftest.map")
  421 + file(WRITE ${ld_script}
  422 +"VERS_1 {
  423 + global: sym;
  424 +};
  425 +
  426 +VERS_2 {
  427 + global: sym;
  428 +} VERS_1;
  429 +")
  430 + set(CMAKE_REQUIRED_LINK_OPTIONS -Wl,--version-script=${ld_script})
  431 + check_c_source_compiles("int main() { return 0; }" HAVE_LD_SCRIPT)
  432 + if(HAVE_LD_SCRIPT)
  433 + set(LD_VERSION_FLAGS
  434 + -Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/libqpdf.map PARENT_SCOPE)
  435 + configure_file(
  436 + "${qpdf_SOURCE_DIR}/libqpdf.map.in"
  437 + "${CMAKE_CURRENT_BINARY_DIR}/libqpdf.map"
  438 + NEWLINE_STYLE UNIX)
  439 + endif()
  440 +endfunction()
  441 +if(NOT WIN32)
  442 + ld_version_script()
  443 +endif()
  444 +
  445 +if(BUILD_SHARED_LIBS)
  446 + add_compile_definitions(DLL_EXPORT)
  447 +
  448 + set(SHARED_LIB libqpdf)
  449 + if(OBJECT_LIB_IS_PIC)
  450 + add_library(${SHARED_LIB} SHARED $<TARGET_OBJECTS:libqpdf_object>)
  451 + else()
  452 + add_library(${SHARED_LIB} SHARED ${libqpdf_SOURCES})
  453 + endif()
  454 + if(WIN32)
  455 + # Goal: the DLL import library should be libqpdf.a or qpdf.lib so
  456 + # that linking with -lqpdf gets you a shared library link on all
  457 + # platforms. The DLL should be qpdf${SONAME}.dll rather than just
  458 + # qpdf.dll. qpdf has always done this, and it gives us some
  459 + # protection against binary incompatible DLLs being installed.
  460 + set(SHARED_OUT qpdf${qpdf_SOVERSION}) # Put API version number in DLL
  461 + if(MINGW)
  462 + # Reference: Platform/Windows-GNU.cmake in the cmake installation
  463 + set(CMAKE_SHARED_LIBRARY_PREFIX "") # libqpdf$v.dll -> qpdf$v.dll
  464 + set(CMAKE_IMPORT_LIBRARY_SUFFIX ".a") # libqpdf.dll.a -> libqpdf.a
  465 + endif()
  466 + if(MSVC)
  467 + # Avoid linker warning from mixing libraries built with /MT and /MD.
  468 + set_target_properties(${SHARED_LIB}
  469 + PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD")
  470 + endif()
  471 + else()
  472 + set(SHARED_OUT qpdf)
  473 + endif()
  474 + # Setting OUTPUT_NAME and ARCHIVE_OUTPUT_NAME separate enables us to
  475 + # have a versioned DLL and an unversioned import library, which
  476 + # gives us semantics similar to ELF shared libraries and makes
  477 + # linking against qpdf the same across all platforms.
  478 + set_target_properties(${SHARED_LIB} PROPERTIES
  479 + OUTPUT_NAME ${SHARED_OUT}
  480 + ARCHIVE_OUTPUT_NAME qpdf
  481 + VERSION ${qpdf_LIBVERSION}
  482 + SOVERSION ${qpdf_SOVERSION}
  483 + POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS})
  484 +
  485 + target_include_directories(${SHARED_LIB}
  486 + SYSTEM PRIVATE ${dep_include_directories})
  487 + target_include_directories(${SHARED_LIB}
  488 + PUBLIC
  489 + $<BUILD_INTERFACE:${qpdf_INCLUDE}>
  490 + $<INSTALL_INTERFACE:include>)
  491 + target_link_directories(${SHARED_LIB} PRIVATE ${dep_link_directories})
  492 + target_link_libraries(${SHARED_LIB} PRIVATE ${dep_link_libraries})
  493 + if(LD_VERSION_FLAGS)
  494 + target_link_options(${SHARED_LIB} PRIVATE ${LD_VERSION_FLAGS})
  495 + endif()
  496 +
  497 + target_include_directories(${SHARED_LIB}
  498 + PRIVATE ${qpdf_SOURCE_DIR}/libqpdf ${CMAKE_CURRENT_BINARY_DIR})
  499 +
  500 + install(TARGETS ${SHARED_LIB}
  501 + EXPORT libqpdfTargets
  502 + TYPE LIBRARY
  503 + COMPONENT ${COMPONENT_LIB}
  504 + NAMELINK_COMPONENT ${COMPONENT_DEV}
  505 + INCLUDES ${qpdf_INCLUDE})
  506 +endif()
  507 +
  508 +if(BUILD_STATIC_LIBS)
  509 + if(BUILD_SHARED_LIBS)
  510 + set(STATIC_LIB libqpdf_static)
  511 + else()
  512 + set(STATIC_LIB libqpdf)
  513 + endif()
  514 + if(OBJECT_LIB_IS_PIC)
  515 + add_library(${STATIC_LIB} STATIC ${libqpdf_SOURCES})
  516 + else()
  517 + add_library(${STATIC_LIB} STATIC $<TARGET_OBJECTS:libqpdf_object>)
  518 + endif()
  519 +
  520 + target_include_directories(${STATIC_LIB}
  521 + SYSTEM PRIVATE ${dep_include_directories})
  522 + target_include_directories(${STATIC_LIB}
  523 + PUBLIC
  524 + $<BUILD_INTERFACE:${qpdf_INCLUDE}>
  525 + $<INSTALL_INTERFACE:include>)
  526 + target_link_directories(${STATIC_LIB}
  527 + INTERFACE $<BUILD_INTERFACE:${dep_link_directories}>
  528 + PRIVATE $<INSTALL_INTERFACE:${dep_link_directories}>)
  529 + target_link_libraries(${STATIC_LIB} INTERFACE ${dep_link_libraries})
  530 +
  531 + # Avoid name clashes on Windows with the the DLL import library.
  532 + if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
  533 + if (WIN32)
  534 + set(STATIC_SUFFIX "_static")
  535 + else()
  536 + set(STATIC_SUFFIX "")
  537 + endif()
  538 + endif()
  539 +
  540 + set_target_properties(${STATIC_LIB} PROPERTIES
  541 + OUTPUT_NAME qpdf${STATIC_SUFFIX}
  542 + VERSION ${PROJECT_VERSION})
  543 + target_include_directories(${STATIC_LIB}
  544 + PRIVATE ${qpdf_SOURCE_DIR}/libqpdf ${CMAKE_CURRENT_BINARY_DIR})
  545 +
  546 + install(TARGETS ${STATIC_LIB}
  547 + EXPORT libqpdfTargets
  548 + TYPE ARCHIVE
  549 + COMPONENT ${COMPONENT_DEV}
  550 + INCLUDES ${qpdf_INCLUDE})
  551 +endif()
  552 +
  553 +configure_file(
  554 + "${qpdf_SOURCE_DIR}/libqpdf.pc.in"
  555 + "${CMAKE_CURRENT_BINARY_DIR}/libqpdf.pc"
  556 + @ONLY NEWLINE_STYLE UNIX)
  557 +if(INSTALL_PKGCONFIG)
  558 + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libqpdf.pc
  559 + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
  560 + COMPONENT ${COMPONENT_DEV})
  561 +endif()
  562 +
  563 +if(INSTALL_CMAKE_PACKAGE)
  564 + include(CMakePackageConfigHelpers)
  565 + configure_package_config_file(
  566 + ${qpdf_SOURCE_DIR}/qpdfConfig.cmake.in
  567 + ${CMAKE_CURRENT_BINARY_DIR}/qpdfConfig.cmake
  568 + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qpdf)
  569 + write_basic_package_version_file(
  570 + "${CMAKE_CURRENT_BINARY_DIR}/qpdfConfigVersion.cmake"
  571 + VERSION ${PROJECT_VERSION}
  572 + COMPATIBILITY SameMajorVersion)
  573 + install(EXPORT libqpdfTargets
  574 + NAMESPACE qpdf::
  575 + FILE libqpdfTargets.cmake
  576 + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qpdf)
  577 + install(FILES
  578 + ${CMAKE_CURRENT_BINARY_DIR}/qpdfConfigVersion.cmake
  579 + ${CMAKE_CURRENT_BINARY_DIR}/qpdfConfig.cmake
  580 + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qpdf)
  581 +endif()
... ...
libtests/CMakeLists.txt 0 → 100644
  1 +set(TEST_PROGRAMS
  2 + cxx11
  3 + aes
  4 + arg_parser
  5 + ascii85
  6 + bits
  7 + buffer
  8 + closed_file_input_source
  9 + concatenate
  10 + dct_compress
  11 + dct_uncompress
  12 + flate
  13 + hex
  14 + input_source
  15 + json
  16 + json_handler
  17 + json_parse
  18 + lzw
  19 + main_from_wmain
  20 + matrix
  21 + md5
  22 + nntree
  23 + numrange
  24 + pdf_version
  25 + pointer_holder
  26 + predictors
  27 + qintc
  28 + qutil
  29 + random
  30 + rc4
  31 + runlength
  32 + sha2
  33 + sparse_array)
  34 +foreach(PROG ${TEST_PROGRAMS})
  35 + add_executable(${PROG} ${PROG}.cc)
  36 + target_link_libraries(${PROG} libqpdf_object)
  37 +endforeach()
  38 +
  39 +# Since libtests link with the object library and don't use the DLL,
  40 +# we don't need to (and shouldn't) add the libqpdf target directory to
  41 +# the path for libtests.
  42 +add_test(
  43 + NAME libtests
  44 + COMMAND ${RUN_QTEST}
  45 + --top ${qpdf_SOURCE_DIR}
  46 + --bin $<TARGET_FILE_DIR:qutil>
  47 + --bin $<TARGET_FILE_DIR:qpdf>
  48 + --code ${qpdf_SOURCE_DIR}/libtests
  49 + --color ${QTEST_COLOR}
  50 + --show-on-failure ${SHOW_FAILED_TEST_OUTPUT}
  51 + --tc "${qpdf_SOURCE_DIR}/libtests/*.cc"
  52 + --tc "${qpdf_SOURCE_DIR}/libqpdf/*.cc"
  53 + --tc "${qpdf_SOURCE_DIR}/libqpdf/qpdf/bits_functions.hh")
... ...
manual/CMakeLists.txt 0 → 100644
  1 +# There is a FindLATEX module, but it does some things we don't care
  2 +# about and doesn't do everything we need.
  3 +find_program(LATEX latex)
  4 +find_program(PDFLATEX pdflatex)
  5 +find_program(LATEXMK latexmk)
  6 +find_program(SPHINX sphinx-build)
  7 +
  8 +# *** NOTE: Never check BUILD_DOC_PDF if BUILD_DOC is not set. See
  9 +# *** comments in top-level CMakeLists.txt.
  10 +
  11 +if(BUILD_DOC)
  12 + if(SPHINX STREQUAL SPHINX-NOTFOUND)
  13 + message(FATAL_ERROR "sphinx-build is required for building documentation")
  14 + endif()
  15 + if(BUILD_DOC_PDF AND
  16 + ((LATEX STREQUAL LATEX-NOTFOUND) OR
  17 + (LATEXMK STREQUAL LATEXMK-NOTFOUND) OR
  18 + (PDFLATEX STREQUAL PDFLATEX-NOTFOUND)))
  19 + message(FATAL_ERROR
  20 + "latex, latexmk, and pdflatex are required to build PDF documentation")
  21 + endif()
  22 +endif()
  23 +
  24 +set(MANUAL_SRC ${qpdf_SOURCE_DIR}/manual)
  25 +foreach(F qpdf.1 fix-qdf.1 zlib-flate.1)
  26 + configure_file(
  27 + ${MANUAL_SRC}/${F}.in
  28 + ${CMAKE_CURRENT_BINARY_DIR}/${F}
  29 + NEWLINE_STYLE UNIX)
  30 +endforeach()
  31 +
  32 +SET(MANUAL_DEPS
  33 + conf.py
  34 + _ext/qpdf.py
  35 + acknowledgement.rst
  36 + cli.rst
  37 + design.rst
  38 + download.rst
  39 + encryption.rst
  40 + index.rst
  41 + installation.rst
  42 + json.rst
  43 + library.rst
  44 + license.rst
  45 + linearization.rst
  46 + object-streams.rst
  47 + overview.rst
  48 + packaging.rst
  49 + qdf.rst
  50 + qpdf-job.rst
  51 + release-notes.rst
  52 + weak-crypto.rst)
  53 +
  54 +# Prevent targets that run ${SPHINX} from running in parallel by using
  55 +# dependencies. This avoids clashes in temporary files that cause the
  56 +# build to fail with the error "_pickle.UnpicklingError: pickle data
  57 +# was truncated". It would be better if we could use order-only
  58 +# dependencies like gnu make to make it possible to build the targets
  59 +# independently.
  60 +set(DOC_HTML_OUTPUT html/index.html)
  61 +set(DOC_SINGLEHTML_OUTPUT singlehtml/index.html)
  62 +set(DOC_PDF_OUTPUT latex/qpdf.pdf)
  63 +if(BUILD_DOC)
  64 + add_custom_command(OUTPUT ${DOC_HTML_OUTPUT}
  65 + COMMAND ${SPHINX} -M html ${MANUAL_SRC} ${CMAKE_CURRENT_BINARY_DIR}
  66 + COMMAND touch ${DOC_HTML_OUTPUT}
  67 + DEPENDS ${MANUAL_DEPS})
  68 + add_custom_command(OUTPUT ${DOC_SINGLEHTML_OUTPUT}
  69 + COMMAND ${SPHINX} -M singlehtml ${MANUAL_SRC} ${CMAKE_CURRENT_BINARY_DIR}
  70 + COMMAND touch ${DOC_SINGLEHTML_OUTPUT}
  71 + DEPENDS ${MANUAL_DEPS})
  72 + add_custom_command(OUTPUT ${DOC_PDF_OUTPUT}
  73 + COMMAND ${SPHINX} -M latexpdf ${MANUAL_SRC} ${CMAKE_CURRENT_BINARY_DIR}
  74 + COMMAND touch ${DOC_PDF_OUTPUT}
  75 + DEPENDS ${MANUAL_DEPS})
  76 + add_custom_target(doc_html DEPENDS ${DOC_HTML_OUTPUT})
  77 + add_custom_target(doc_singlehtml DEPENDS ${DOC_SINGLEHTML_OUTPUT})
  78 + add_dependencies(doc_singlehtml doc_html)
  79 + add_custom_target(doc_pdf DEPENDS ${DOC_PDF_OUTPUT})
  80 + add_custom_target(doc ALL)
  81 + if(BUILD_DOC_PDF)
  82 + add_dependencies(doc doc_pdf)
  83 + if(BUILD_DOC_HTML)
  84 + add_dependencies(doc_pdf doc_singlehtml)
  85 + endif()
  86 + elseif(BUILD_DOC_HTML)
  87 + add_dependencies(doc doc_singlehtml)
  88 + endif()
  89 +
  90 + if(BUILD_DOC_DIST)
  91 + set(DOC_DIST_HTML doc-dist/manual-html)
  92 + set(DOC_DIST_SINGLEHTML doc-dist/manual-single-page-html)
  93 + set(DOC_DIST_PDF doc-dist/qpdf-manual.pdf)
  94 + add_custom_command(
  95 + OUTPUT
  96 + ${DOC_DIST_HTML}
  97 + ${DOC_DIST_SINGLEHTML}
  98 + ${DOC_DIST_PDF}
  99 + COMMAND rm -rf doc-dist
  100 + COMMAND mkdir -p doc-dist
  101 + COMMAND cp -r html ${DOC_DIST_HTML}
  102 + COMMAND cp -r singlehtml ${DOC_DIST_SINGLEHTML}
  103 + COMMAND cp -r ${DOC_PDF_OUTPUT} ${DOC_DIST_PDF}
  104 + DEPENDS ${DOC_HTML_OUTPUT} ${DOC_SINGLEHTML_OUTPUT} ${DOC_PDF_OUTPUT})
  105 + add_custom_target(doc_dist ALL
  106 + DEPENDS ${DOC_DIST_HTML} ${DOC_DIST_SINGLEHTML} ${DOC_DIST_PDF})
  107 + add_dependencies(doc_dist doc)
  108 + endif()
  109 +endif()
  110 +
  111 +# INSTALL_MANUAL is not dependent on building doc -- we sometimes drop in
  112 +# pre-built doc when creating distributions.
  113 +if(INSTALL_MANUAL)
  114 + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-dist/
  115 + TYPE DOC
  116 + COMPONENT ${COMPONENT_DOC})
  117 +else()
  118 + install(FILES ${qpdf_SOURCE_DIR}/README-doc.txt
  119 + TYPE DOC
  120 + COMPONENT ${COMPONENT_DOC})
  121 +endif()
  122 +
  123 +if(NOT WIN32)
  124 + # There's no reason to install manual pages in a Windows
  125 + # environment, especially when all they do is refer people to the
  126 + # manual.
  127 + install(FILES
  128 + ${CMAKE_CURRENT_BINARY_DIR}/qpdf.1
  129 + ${CMAKE_CURRENT_BINARY_DIR}/fix-qdf.1
  130 + ${CMAKE_CURRENT_BINARY_DIR}/zlib-flate.1
  131 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
  132 + COMPONENT ${COMPONENT_DOC})
  133 +endif()
... ...
qpdf/CMakeLists.txt 0 → 100644
  1 +set(MAIN_CXX_PROGRAMS
  2 + qpdf
  3 + fix-qdf
  4 + pdf_from_scratch
  5 + test_driver
  6 + test_large_file
  7 + test_parsedoffset
  8 + test_pdf_doc_encoding
  9 + test_pdf_unicode
  10 + test_renumber
  11 + test_shell_glob
  12 + test_tokenizer
  13 + test_unicode_filenames
  14 + test_xref)
  15 +set(MAIN_C_PROGRAMS
  16 + qpdf-ctest
  17 + qpdfjob-ctest)
  18 +
  19 +foreach(PROG ${MAIN_CXX_PROGRAMS})
  20 + add_executable(${PROG} ${PROG}.cc)
  21 + target_link_libraries(${PROG} libqpdf)
  22 +endforeach()
  23 +foreach(PROG ${MAIN_C_PROGRAMS})
  24 + add_executable(${PROG} ${PROG}.c)
  25 + target_link_libraries(${PROG} libqpdf)
  26 + set_property(TARGET ${PROG} PROPERTY LINKER_LANGUAGE CXX)
  27 +endforeach()
  28 +target_include_directories(qpdf-ctest PRIVATE ${CMAKE_BINARY_DIR}/libqpdf)
  29 +
  30 +foreach(B qpdf test_unicode_filenames fix-qdf test_shell_glob)
  31 + if(WINDOWS_WMAIN_COMPILE)
  32 + target_compile_options(${B} PRIVATE ${WINDOWS_WMAIN_COMPILE})
  33 + endif()
  34 + if(WINDOWS_WMAIN_LINK)
  35 + target_link_options(${B} PRIVATE ${WINDOWS_WMAIN_LINK})
  36 + endif()
  37 +endforeach()
  38 +
  39 +add_test(
  40 + NAME qpdf
  41 + COMMAND ${RUN_QTEST}
  42 + --top ${qpdf_SOURCE_DIR}
  43 + --bin $<TARGET_FILE_DIR:qpdf>
  44 + --bin $<TARGET_FILE_DIR:libqpdf> # for Windows to find DLL
  45 + --code ${qpdf_SOURCE_DIR}/qpdf
  46 + --color ${QTEST_COLOR}
  47 + --show-on-failure ${SHOW_FAILED_TEST_OUTPUT}
  48 + --tc "${qpdf_SOURCE_DIR}/qpdf/*.cc"
  49 + --tc "${qpdf_SOURCE_DIR}/qpdf/*.c"
  50 + --tc "${qpdf_SOURCE_DIR}/libqpdf/*.cc")
  51 +
  52 +install(TARGETS qpdf fix-qdf
  53 + TYPE RUNTIME
  54 + COMPONENT ${COMPONENT_CLI})
  55 +
  56 +if(MINGW)
  57 + # For MSVC, including InstallRequiredSystemLibraries in the
  58 + # top-level CMakeLists.txt is sufficient. For mingw, we have to copy
  59 + # mingw libraries in ourselves.
  60 + set(ONE_GNU_DLL extra-dlls/libstdc++-6.dll)
  61 + add_custom_command(OUTPUT ${ONE_GNU_DLL}
  62 + COMMAND
  63 + perl ${qpdf_SOURCE_DIR}/copy_dlls
  64 + qpdf.exe
  65 + ${CMAKE_BINARY_DIR}/libqpdf
  66 + extra-dlls)
  67 + add_custom_target(extra_dlls ALL DEPENDS ${ONE_GNU_DLL})
  68 + add_dependencies(extra_dlls qpdf)
  69 + if(BUILD_SHARED_LIBS)
  70 + set(EXTRA_DLL_COMPONENT ${COMPONENT_LIB})
  71 + else()
  72 + set(EXTRA_DLL_COMPONENT ${COMPONENT_CLI})
  73 + endif()
  74 + # The trailing / prevents "extra-dlls" from being created in bin.
  75 + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/extra-dlls/
  76 + TYPE BIN
  77 + COMPONENT ${EXTRA_DLL_COMPONENT})
  78 +endif()
... ...
qpdfConfig.cmake.in 0 → 100644
  1 +@PACKAGE_INIT@
  2 +include("${CMAKE_CURRENT_LIST_DIR}/libqpdfTargets.cmake")
... ...
zlib-flate/CMakeLists.txt 0 → 100644
  1 +add_executable(zlib-flate zlib-flate.cc)
  2 +target_link_libraries(zlib-flate libqpdf)
  3 +
  4 +add_test(
  5 + NAME zlib-flate
  6 + COMMAND ${RUN_QTEST}
  7 + --top ${qpdf_SOURCE_DIR}
  8 + --bin $<TARGET_FILE_DIR:zlib-flate>
  9 + --bin $<TARGET_FILE_DIR:libqpdf> # for Windows to find DLL
  10 + --code ${qpdf_SOURCE_DIR}/zlib-flate
  11 + --color ${QTEST_COLOR}
  12 + --show-on-failure ${SHOW_FAILED_TEST_OUTPUT})
  13 +
  14 +install(TARGETS zlib-flate
  15 + TYPE RUNTIME
  16 + COMPONENT ${COMPONENT_CLI})
... ...