Code View

cparse / cparse-1.3.0.2 / CMakeLists.txt
cmake_minimum_required( VERSION 3.20 )

set(PROJECT_NAME cparse)
project(${PROJECT_NAME} VERSION 1.3.0.2
        DESCRIPTION "Small hand-written recursive-descent parser core (Cursor / Parser / Generator)")

# ── Standalone vs embedded detection ─────────────────────────────────────────
# CPARSE_STANDALONE is ON when this CMakeLists is the top-level project and OFF
# when cparse is consumed via add_subdirectory() (e.g. from fson, which is in
# turn embedded in FFS). In embedded mode tests/examples default OFF, the build
# type is left to the host, and the CPack section is skipped so the host's
# packaging is untouched.
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
    set(CPARSE_STANDALONE ON)
else()
    set(CPARSE_STANDALONE OFF)
endif()

option(TESTING "Compile Test Targets"    ${CPARSE_STANDALONE})
option(EXAMPLE "Compile Example Targets" ${CPARSE_STANDALONE})
# "examples/" (plural): one directory per example (toy-calc, key-value,
# csv-lite), each with its own src/ (buildable CMakeLists.txt) and doc/
# (railroad-diagram .rrd source + .svg). Ships in the release source
# archive like everything else in the tree — see downloads.md.

# Install component for the runtime artefacts (libcparse). A host project may
# override this so the library is staged and deployed with its own components.
set(CPARSE_INSTALL_COMPONENT "cparse" CACHE STRING
    "CMake install component for the cparse runtime library")

if(CPARSE_STANDALONE)
    find_program(CCACHE_PROGRAM ccache)
    if(CCACHE_PROGRAM)
        set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
    endif()
endif()

include(GNUInstallDirs)

set(CMAKE_VERBOSE_MAKEFILE OFF)
set(CMAKE_CXX_STANDARD 20)
if(CPARSE_STANDALONE AND NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Debug)
endif()

# ctest is enabled whenever TESTING or EXAMPLE is on — the examples/ smoke
# tests (run each example, diff its output against the walkthrough's
# documented transcript) are plain add_test()/diff, no GTest needed, so they
# must not depend on GTest being found. This has to run BEFORE
# add_subdirectory(examples) below: enable_testing() only affects
# subdirectories added after it.
if(${TESTING} OR ${EXAMPLE})
    enable_testing()
endif()

# Setup gTest
if (${TESTING})
find_package(GTest QUIET)

if(${GTest_FOUND})
  include_directories(${GTEST_INCLUDE_DIR})
else()
  message(STATUS "GTest not found, disabling tests")
  set(TESTING OFF)
endif()
endif()

# The project

add_subdirectory(src)

if(${EXAMPLE} AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples")
    add_subdirectory(examples)
    message(STATUS "The examples directory added")
endif()

if(${TESTING} AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test")
    add_subdirectory(test)
    message(STATUS "The test directory added")
endif()

# ── API documentation (Doxygen) ─────────────────────────────────────────────
# `cmake --build <dir> --target docs` writes the HTML tree to <dir>/docs/html/.
# That same tree is published at https://cparse.fedem.eu/api (dropped under the
# deployed tenant's static/api/). The hand-written companion is the Reference
# Manual at /reference. Doxygen absent → no `docs` target, nothing else changes.
# Standalone only: an embedding host would collide on the target name.
if(CPARSE_STANDALONE)
    find_package(Doxygen QUIET OPTIONAL_COMPONENTS dot)
    if(DOXYGEN_FOUND)
        set(DOXYGEN_INPUT_DIR  "${CMAKE_CURRENT_SOURCE_DIR}/src/cparse")
        set(DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/docs")

        # The header carries a 4-part version; the Doxygen tree and the release
        # archives use the 3-part form.
        #
        # FORCE is load-bearing, not decorative: set(... CACHE ...) without it
        # is a no-op once the cache entry already exists (e.g. ws-release.sh
        # reuses build/Release/ across releases), so a version bump would
        # silently NOT reach the generated docs — the previous release's
        # number would keep showing forever. FORCE means this can no longer be
        # overridden with -DDOXYGEN_PROJECT_NUMBER=...; nothing relies on that.
        set(DOXYGEN_PROJECT_NUMBER
            "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
            CACHE STRING "Version string shown in the Doxygen HTML header" FORCE)

        if(TARGET Doxygen::dot)
            set(DOXYGEN_HAVE_DOT YES)
        else()
            set(DOXYGEN_HAVE_DOT NO)
        endif()

        option(CPARSE_DOCS_WARN_AS_ERROR
               "Fail the 'docs' build on any Doxygen warning" OFF)
        if(CPARSE_DOCS_WARN_AS_ERROR)
            set(DOXYGEN_WARN_AS_ERROR FAIL_ON_WARNINGS)
        else()
            set(DOXYGEN_WARN_AS_ERROR NO)
        endif()

        configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
                       "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" @ONLY)

        add_custom_target(docs
            COMMAND ${CMAKE_COMMAND} -E make_directory "${DOXYGEN_OUTPUT_DIR}"
            COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
            WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
            COMMENT "Doxygen → ${DOXYGEN_OUTPUT_DIR}/html/index.html"
            VERBATIM)
    else()
        message(STATUS "Doxygen not found — 'docs' target unavailable")
    endif()
endif()

#
# installation package
#
configure_file(cparse.pc.in ${CMAKE_CURRENT_BINARY_DIR}/cparse.pc @ONLY)

install(TARGETS cparse
        LIBRARY
            COMPONENT   ${CPARSE_INSTALL_COMPONENT}
            DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cparse.pc
        COMPONENT ${CPARSE_INSTALL_COMPONENT}
        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)

if(CPARSE_STANDALONE)
## create packages
set(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} cparse)

set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_RELEASE "1")
set(CPACK_PACKAGE_DESCRIPTION "A small parser library core project")
set(CPACK_PACKAGE_VENDOR "Fedem Software")
set(CPACK_PACKAGE_CONTACT "Fehmi Demiralp <demiralp@fedem.eu>")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_PACKAGING_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_HOMEPAGE_URL "https://cparse.fedem.eu")
set(CPACK_PACKAGE_LICENSE "MIT")
set(CPACK_GENERATOR 7Z TGZ ZIP DEB RPM)

# RPM-specific settings
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_COMPONENT_CPARSE_DISPLAY_NAME "CParse Package")
set(CPACK_COMPONENT_CPARSE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")

set(CPACK_RPM_CPARSE_PACKAGE_GROUP "Development/Tools")
set(CPACK_RPM_CPARSE_PACKAGE_LICENSE "MIT")
set(CPACK_RPM_CPARSE_PACKAGE_URL "https://cparse.fedem.eu")
set(CPACK_RPM_CPARSE_PACKAGE_ARCHITECTURE "x86_64")
set(CPACK_RPM_CPARSE_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE})
set(CPACK_RPM_CPARSE_PACKAGE_REQUIRES "gcc >= 12.0")

set(CPACK_ARCHIVE_CPARSE_FILE_NAME "C${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)

# Debian-specific settings
set(CPACK_DEBIAN_PACKAGE_DEPENDS "")

include(CPack)
endif()  # CPARSE_STANDALONE