mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-23 03:18:59 +00:00
407 lines
12 KiB
CMake
407 lines
12 KiB
CMake
# manual/installation.rst mentions the minimum cmake version.
|
|
cmake_minimum_required(VERSION 3.16)
|
|
|
|
# make_dist expects the version line to be on a line by itself after
|
|
# the project line. When updating the version, check make_dist for all
|
|
# the places it has to be updated. The doc configuration and CI build
|
|
# also find the version number here. generate_auto_job also reads the
|
|
# version from here.
|
|
project(qpdf
|
|
VERSION 11.9.0
|
|
LANGUAGES C CXX)
|
|
|
|
# Enable correct rpath handling for MacOSX
|
|
cmake_policy(SET CMP0042 NEW)
|
|
# Honor CMAKE_REQUIRED_LIBRARIES when checking for include files
|
|
cmake_policy(SET CMP0075 NEW)
|
|
|
|
# *** OPTIONS ***
|
|
|
|
# Keep all options here. It's easier to see the interdependencies this
|
|
# way than spreading them throughout the files.
|
|
#
|
|
# ***** Keep manual/installation.rst (_build-options) up to date. *****
|
|
|
|
include(CMakeDependentOption)
|
|
|
|
# CMAKE_DEPENDENT_OPTION(
|
|
# OPTION "Description" default-value-if-visible
|
|
# "when-visible" value-if-not-visible)
|
|
|
|
# Don't write tests based on MAINTAINER_MODE or CI_MODE. Instead, use
|
|
# them as the basis for dependent options.
|
|
|
|
option(MAINTAINER_MODE "Set options for developing qpdf" OFF)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
CI_MODE "Set options for running in CI" OFF
|
|
"NOT MAINTAINER_MODE" OFF)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
WERROR "Treat compiler warnings as errors" OFF
|
|
"NOT MAINTAINER_MODE; NOT CI_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
CHECK_SIZES "Compare sizes.cc with classes in public API" OFF
|
|
"NOT MAINTAINER_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
GENERATE_AUTO_JOB "Automatically regenerate job files" OFF
|
|
"NOT MAINTAINER_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
ENABLE_QTC "Enable QTC test coverage" OFF
|
|
"NOT MAINTAINER_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
SHOW_FAILED_TEST_OUTPUT "Show qtest output on failure" OFF
|
|
"NOT CI_MODE" ON)
|
|
|
|
# To allow building doc to be disabled in maintainer mode, handle the
|
|
# condition manually rather than using a dependent option.
|
|
if(MAINTAINER_MODE)
|
|
set(default_BUILD_DOC ON)
|
|
else()
|
|
set(default_BUILD_DOC OFF)
|
|
endif()
|
|
option(BUILD_DOC "Build documentation" ${default_BUILD_DOC})
|
|
# The values of BUILD_DOC_HTML and BUILD_DOC_PDF are ignored without
|
|
# BUILD_DOC, so setting them to ON when not visible forces them to be
|
|
# on in MAINTAINER_MODE and is harmless if BUILD_DOC is off.
|
|
CMAKE_DEPENDENT_OPTION(
|
|
BUILD_DOC_HTML "Build HTML documentation"
|
|
ON "BUILD_DOC;NOT MAINTAINER_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
BUILD_DOC_PDF "Build PDF documentation"
|
|
ON "BUILD_DOC;NOT MAINTAINER_MODE" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
BUILD_DOC_DIST "Create distribution of manual" ON
|
|
"BUILD_DOC_PDF;BUILD_DOC_HTML" OFF)
|
|
|
|
option(ENABLE_COVERAGE "Enable coverage reporting" OFF)
|
|
option(BUILD_SHARED_LIBS "Build qpdf shared libraries" ON)
|
|
option(BUILD_STATIC_LIBS "Build qpdf static libraries" ON)
|
|
option(QTEST_COLOR "Whether qtest's output should be in color" ON)
|
|
option(USE_INSECURE_RANDOM "Use insecure random numbers" OFF)
|
|
option(SKIP_OS_SECURE_RANDOM
|
|
"Suppress use of OS-provided secure random numbers" OFF)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
AVOID_WINDOWS_HANDLE "Avoid use of HANDLE in Windows" OFF
|
|
"WIN32" OFF)
|
|
|
|
option(OSS_FUZZ "Specific build configuration for the oss-fuzz project" OFF)
|
|
|
|
option(USE_IMPLICIT_CRYPTO "Enable any available external crypto provider" ON)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
ALLOW_CRYPTO_NATIVE "Allow native crypto as as fallback" ON
|
|
"USE_IMPLICIT_CRYPTO" OFF)
|
|
CMAKE_DEPENDENT_OPTION(
|
|
REQUIRE_CRYPTO_NATIVE "Require native crypto provider" OFF
|
|
"NOT MAINTAINER_MODE; NOT CI_MODE" ON)
|
|
option(REQUIRE_CRYPTO_OPENSSL "Require openssl crypto" OFF)
|
|
option(REQUIRE_CRYPTO_GNUTLS "Require gnutls crypto" OFF)
|
|
set(DEFAULT_CRYPTO CACHE STRING "")
|
|
option(DEFAULT_CRYPTO
|
|
"Specify default crypto; otherwise chosen automatically" "")
|
|
|
|
# INSTALL_MANUAL is not dependent on building docs. When creating some
|
|
# distributions, we build the doc in one run, copy doc-dist in, and
|
|
# install it elsewhere.
|
|
option(INSTALL_MANUAL "Install documentation" OFF)
|
|
|
|
option(INSTALL_PKGCONFIG "Install pkgconfig file" ON)
|
|
option(INSTALL_CMAKE_PACKAGE "Install cmake package files" ON)
|
|
option(INSTALL_EXAMPLES "Install example files" ON)
|
|
|
|
option(FUTURE "Include ABI-breaking changes CONSIDERED for the next major release" OFF)
|
|
option(CXX_NEXT "Build with next C++ standard version" OFF)
|
|
|
|
# *** END OPTIONS ***
|
|
|
|
if(NOT (BUILD_STATIC_LIBS OR BUILD_SHARED_LIBS))
|
|
message(
|
|
FATAL_ERROR "At least one of static or shared libraries must be built")
|
|
endif()
|
|
|
|
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
|
|
add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:POINTERHOLDER_TRANSITION=4>)
|
|
|
|
if(ENABLE_QTC)
|
|
set(ENABLE_QTC_ARG)
|
|
else()
|
|
add_compile_definitions(QPDF_DISABLE_QTC=1)
|
|
set(ENABLE_QTC_ARG --disable-tc)
|
|
endif()
|
|
|
|
if(FUTURE)
|
|
add_compile_definitions(QPDF_FUTURE=1)
|
|
endif()
|
|
|
|
enable_testing()
|
|
set(RUN_QTEST perl ${qpdf_SOURCE_DIR}/run-qtest ${ENABLE_QTC_ARG})
|
|
|
|
if(WIN32)
|
|
find_program(COPY_COMMAND NAMES cp copy)
|
|
if(COPY_COMMAND STREQUAL "COPY_COMMAND-NOTFOUND")
|
|
set(COPY_COMMAND "copy")
|
|
endif()
|
|
else()
|
|
set(COPY_COMMAND "cp")
|
|
endif()
|
|
|
|
# For a long time, qpdf used libtool's version system. We are no
|
|
# longer doing that, but to avoid potential conflict with older
|
|
# versions, continue to have the shared library symlink point to a
|
|
# file whose version shares minor and patch with the project version
|
|
# and major with the SOVERSION. Starting with the transition to cmake,
|
|
# increment SOVERSION every time we increment the project major
|
|
# version. This works because qpdf uses semantic versioning. qpdf 10.x
|
|
# was libqpdf28, so start from there.
|
|
|
|
if(FUTURE)
|
|
math(EXPR qpdf_SOVERSION 0)
|
|
set(qpdf_LIBVERSION 0)
|
|
else()
|
|
math(EXPR qpdf_SOVERSION "${PROJECT_VERSION_MAJOR} + 18")
|
|
set(qpdf_LIBVERSION ${qpdf_SOVERSION}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
|
endif()
|
|
|
|
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
|
message(FATAL_ERROR "
|
|
Please build with cmake in a subdirectory, e.g.
|
|
mkdir build
|
|
cmake ..
|
|
cmake --build .
|
|
Please remove CMakeCache.txt and the CMakeFiles directories.")
|
|
endif()
|
|
|
|
if(CXX_NEXT)
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
else()
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
endif()
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
|
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
|
|
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
|
|
if(WIN32 AND NOT SKIP_OS_SECURE_RANDOM)
|
|
list(APPEND CMAKE_REQUIRED_LIBRARIES Advapi32)
|
|
endif()
|
|
|
|
include(CheckCXXSourceCompiles)
|
|
set(ATOMIC_LIBRARY)
|
|
function(check_atomic)
|
|
foreach(I 0 1)
|
|
if(I)
|
|
set(CMAKE_REQUIRED_LIBRARIES atomic)
|
|
endif()
|
|
check_cxx_source_compiles(
|
|
"#include <atomic>
|
|
int main() {
|
|
static std::atomic<unsigned long long> a{0};
|
|
a = a.fetch_add(1LL);
|
|
return 0;
|
|
}"
|
|
ATOMIC_WORKED${I})
|
|
if(ATOMIC_WORKED0)
|
|
return()
|
|
endif()
|
|
endforeach()
|
|
if(ATOMIC_WORKED1)
|
|
set(ATOMIC_LIBRARY atomic PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
check_atomic()
|
|
|
|
set(WINDOWS_WMAIN_COMPILE "")
|
|
set(WINDOWS_WMAIN_LINK "")
|
|
if(WIN32)
|
|
function(check_wmain)
|
|
foreach(I 0 1)
|
|
if(NOT WINDOWS_WMAIN_COMPILE)
|
|
if(I)
|
|
set(CMAKE_REQUIRED_LINK_OPTIONS -municode)
|
|
endif()
|
|
check_cxx_source_compiles(
|
|
"#include <windows.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
extern \"C\"
|
|
int wmain(int argc, wchar_t* argv[])
|
|
{
|
|
size_t x = wcslen(argv[0]);
|
|
return 0;
|
|
}
|
|
"
|
|
WMAIN_WORKED${I})
|
|
endif()
|
|
endforeach()
|
|
if(WMAIN_WORKED1 OR WMAIN_WORKED1)
|
|
set(WINDOWS_WMAIN_COMPILE -DWINDOWS_WMAIN PARENT_SCOPE)
|
|
if(WMAIN_WORKED1 AND NOT WMAIN_WORKED0)
|
|
set(WINDOWS_WMAIN_LINK -municode PARENT_SCOPE)
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
check_wmain()
|
|
endif()
|
|
|
|
if(MSVC)
|
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS -link setargv.obj)
|
|
list(APPEND WINDOWS_WMAIN_LINK -link wsetargv.obj)
|
|
endif()
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
# Compiler flags
|
|
#
|
|
# **NOTE** -- each flag must have its own cache variable.
|
|
|
|
include(qpdfCheckFlag)
|
|
if(WERROR)
|
|
if(MSVC)
|
|
add_compile_options(/WX)
|
|
else()
|
|
qpdf_maybe_add_flag(C -Werror flag_werror)
|
|
endif()
|
|
endif()
|
|
|
|
if(MSVC)
|
|
# /Gy combines identical functions -- useful with C++ templates
|
|
add_compile_options(/Gy)
|
|
add_compile_options(/W3) # warning level 3
|
|
else()
|
|
qpdf_maybe_add_flag(C -Wall flag_wall)
|
|
qpdf_maybe_add_flag(C -Wconversion flag_conversion)
|
|
qpdf_maybe_add_flag(C -Wsign-conversion flag_sign-conversion)
|
|
qpdf_maybe_add_flag(C -Wshadow=local flag_shadow_local)
|
|
qpdf_maybe_add_flag(CXX -Wold-style-cast flag_old-style-cast)
|
|
endif()
|
|
|
|
# We don't include the jpeg library's include path in the PUBLIC
|
|
# interface for libqpdf since only Pl_DCT.hh requires it. This is
|
|
# documented. Some examples and tests use it though so we have to
|
|
# define it. CMakeLists.txt for libqpdf sets the value for
|
|
# JPEG_INCLUDE which can be selectively added to include paths other
|
|
# tools.
|
|
set(JPEG_INCLUDE)
|
|
|
|
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
|
set(WORDSIZE 64)
|
|
else()
|
|
set(WORDSIZE 32)
|
|
endif()
|
|
if(MSVC)
|
|
set(CPACK_SYSTEM_NAME "msvc${WORDSIZE}")
|
|
elseif(MINGW)
|
|
set(CPACK_SYSTEM_NAME "mingw${WORDSIZE}")
|
|
endif()
|
|
set(CPACK_RESOURCE_FILE_LICENSE "${qpdf_SOURCE_DIR}/LICENSE.txt")
|
|
set(CPACK_PACKAGE_HOMEPAGE_URL "https://qpdf.sourceforge.io/")
|
|
set(CPACK_NSIS_MUI_ICON "${qpdf_SOURCE_DIR}/logo/qpdf.ico")
|
|
|
|
if(ENABLE_COVERAGE)
|
|
add_compile_options(--coverage -O0)
|
|
add_link_options(--coverage)
|
|
endif()
|
|
|
|
include(CPack)
|
|
|
|
# Install components -- documented in _installation in
|
|
# manual/installation.rst.
|
|
set(COMPONENT_DEV "dev")
|
|
set(COMPONENT_LIB "lib") # runtime library
|
|
set(COMPONENT_CLI "cli")
|
|
set(COMPONENT_DOC "doc")
|
|
set(COMPONENT_EXAMPLES "examples") # example sources
|
|
|
|
if(WIN32)
|
|
include(InstallRequiredSystemLibraries)
|
|
endif()
|
|
|
|
set(auto_job_inputs
|
|
# Keep in sync with SOURCES in generate_auto_job
|
|
generate_auto_job
|
|
CMakeLists.txt
|
|
manual/_ext/qpdf.py
|
|
job.yml
|
|
manual/cli.rst
|
|
manual/qpdf.1.in
|
|
)
|
|
|
|
set(auto_job_outputs
|
|
# Keep in sync with DESTS in generate_auto_job
|
|
libqpdf/qpdf/auto_job_decl.hh
|
|
libqpdf/qpdf/auto_job_init.hh
|
|
libqpdf/qpdf/auto_job_help.hh
|
|
libqpdf/qpdf/auto_job_schema.hh
|
|
libqpdf/qpdf/auto_job_json_decl.hh
|
|
libqpdf/qpdf/auto_job_json_init.hh
|
|
manual/qpdf.1
|
|
)
|
|
|
|
if(GENERATE_AUTO_JOB)
|
|
add_custom_command(
|
|
OUTPUT ${auto_job_outputs}
|
|
COMMAND ${qpdf_SOURCE_DIR}/generate_auto_job --generate
|
|
WORKING_DIRECTORY ${qpdf_SOURCE_DIR}
|
|
DEPENDS ${auto_job_inputs})
|
|
add_custom_target(auto_job_files ALL DEPENDS ${auto_job_outputs})
|
|
endif()
|
|
|
|
add_test(
|
|
NAME check-assert
|
|
COMMAND perl ${qpdf_SOURCE_DIR}/check_assert)
|
|
|
|
# add_subdirectory order affects test order
|
|
add_subdirectory(include)
|
|
add_subdirectory(libqpdf)
|
|
add_subdirectory(compare-for-test)
|
|
add_subdirectory(qpdf)
|
|
add_subdirectory(libtests)
|
|
add_subdirectory(examples)
|
|
add_subdirectory(zlib-flate)
|
|
add_subdirectory(manual)
|
|
add_subdirectory(fuzz)
|
|
|
|
# We don't need to show everything -- just the things that we really
|
|
# need to be sure are right or that are turned on or off with complex
|
|
# logic.
|
|
get_property(MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
message(STATUS "")
|
|
message(STATUS "*** Summary ***")
|
|
message(STATUS " qpdf version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
|
if(MULTI_CONFIG)
|
|
message(STATUS " build type: specify --config at build time")
|
|
elseif(CMAKE_BUILD_TYPE)
|
|
message(STATUS " build type: ${CMAKE_BUILD_TYPE}")
|
|
endif()
|
|
message(STATUS " build shared libraries: ${BUILD_SHARED_LIBS}")
|
|
message(STATUS " build static libraries: ${BUILD_STATIC_LIBS}")
|
|
message(STATUS " build manual: ${BUILD_DOC}")
|
|
message(STATUS " compiler warnings are errors: ${WERROR}")
|
|
message(STATUS " QTC test coverage: ${ENABLE_QTC}")
|
|
message(STATUS " include future changes: ${FUTURE}")
|
|
message(STATUS " system: ${CPACK_SYSTEM_NAME}")
|
|
message(STATUS "")
|
|
message(STATUS "*** Options Summary ***")
|
|
foreach(PROP
|
|
COMPILE_OPTIONS INTERFACE_COMPILE_OPTIONS
|
|
COMPILE_DEFINITIONS INTERFACE_COMPILE_DEFINITIONS
|
|
INCLUDE_DIRECTORIES INTERFACE_INCLUDE_DIRECTORIES
|
|
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
|
LINK_OPTIONS INTERFACE_LINK_OPTIONS
|
|
LINK_LIBRARIES INTERFACE_LINK_LIBRARIES
|
|
LINK_DIRECTORIES INTERFACE_LINK_DIRECTORIES)
|
|
get_target_property(VAL libqpdf ${PROP})
|
|
if(NOT (VAL STREQUAL "VAL-NOTFOUND"))
|
|
message(STATUS " ${PROP}: ${VAL}")
|
|
endif()
|
|
endforeach()
|
|
if(APPLE)
|
|
message(STATUS " CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}")
|
|
endif()
|
|
message(STATUS "")
|
|
message(STATUS "See above for crypto summary.")
|
|
message(STATUS "")
|
|
if(NOT (MULTI_CONFIG OR CMAKE_BUILD_TYPE))
|
|
message(WARNING " CMAKE_BUILD_TYPE is not set; using default settings")
|
|
endif()
|