172 lines
7.4 KiB
CMake
172 lines
7.4 KiB
CMake
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# SPDX-FileCopyrightText: 2025 ai-ad4 and the FreePDFEditor contributors
|
|
# spike/CMakeLists.txt
|
|
#
|
|
# M0 feasibility spikes (§14). Each spike is its own executable so it can be run
|
|
# independently and its results reported separately by CI. The spikes link only
|
|
# against the leaf libraries they exercise (QPDF here), not against Qt.
|
|
|
|
# Find QPDF. System packages (Debian libqpdf-dev) install the config under the
|
|
# multiarch lib dir; vcpkg installs it under its installed tree. Search both.
|
|
find_package(QPDF CONFIG QUIET
|
|
HINTS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/local /usr)
|
|
|
|
# Fall back to a pkg-config probe if the CMake config wasn't installed.
|
|
if(NOT QPDF_FOUND)
|
|
find_package(PkgConfig QUIET)
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(QPDF libqpdf IMPORTED_TARGET)
|
|
endif()
|
|
endif()
|
|
|
|
# FreeType is shared by Spike B step 1 (cmap fallback) and Spike C (subset
|
|
# growth). Discover it once here so both can use the PkgConfig::FREETYPE target.
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(FREETYPE freetype2 IMPORTED_TARGET)
|
|
endif()
|
|
|
|
if(NOT QPDF_FOUND AND NOT TARGET PkgConfig::QPDF)
|
|
message(STATUS
|
|
"QPDF not found — Spike A (verbatim round-trip) will not be built. "
|
|
"Install qpdf (vcpkg, system package, or from source) to enable it.")
|
|
return()
|
|
endif()
|
|
|
|
# The QPDF CMake config exports `qpdf::libqpdf` (system packages, e.g. Debian's
|
|
# libqpdf-dev) and/or `QPDF::qpdf` (vcpkg). pkg-config yields PkgConfig::QPDF.
|
|
# Accept any of them.
|
|
if(TARGET qpdf::libqpdf)
|
|
set(_fpe_qpdf_target qpdf::libqpdf)
|
|
elseif(TARGET QPDF::qpdf)
|
|
set(_fpe_qpdf_target QPDF::qpdf)
|
|
elseif(TARGET PkgConfig::QPDF)
|
|
set(_fpe_qpdf_target PkgConfig::QPDF)
|
|
else()
|
|
message(WARNING "QPDF found but no known imported target — Spike A skipped.")
|
|
return()
|
|
endif()
|
|
|
|
add_executable(spike_a_verbatim_roundtrip
|
|
common/SpikeRunner.cpp
|
|
common/SpikeRunner.h
|
|
A_verbatim_roundtrip/main.cpp
|
|
A_verbatim_roundtrip/Roundtrip.cpp
|
|
A_verbatim_roundtrip/Roundtrip.h
|
|
)
|
|
target_include_directories(spike_a_verbatim_roundtrip PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
target_link_libraries(spike_a_verbatim_roundtrip PRIVATE ${_fpe_qpdf_target})
|
|
target_compile_features(spike_a_verbatim_roundtrip PRIVATE cxx_std_20)
|
|
freepdfeditor_apply_warnings(spike_a_verbatim_roundtrip)
|
|
freepdfeditor_apply_hardening(spike_a_verbatim_roundtrip)
|
|
|
|
# --- Spike B: glyph→Unicode + line/paragraph reconstruction (§14 step 5) ---
|
|
# The reconstruction pipeline (§4.1 steps 2-5) is pure C++ on the synthetic
|
|
# in-memory model, so it has no third-party dependency for the M0 spike. The
|
|
# glyph→Unicode step 1 (font cmap / ToUnicode) is exercised separately once
|
|
# FreeType/HarfBuzz are wired into the production L3 interpreter in M2.
|
|
add_executable(spike_b_reconstruction
|
|
common/SpikeRunner.cpp
|
|
common/SpikeRunner.h
|
|
B_reconstruction/main.cpp
|
|
B_reconstruction/Reconstruct.cpp
|
|
B_reconstruction/Reconstruct.h
|
|
B_reconstruction/Corpus.cpp
|
|
B_reconstruction/Corpus.h
|
|
B_reconstruction/GlyphRun.h
|
|
)
|
|
target_include_directories(spike_b_reconstruction PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
target_compile_features(spike_b_reconstruction PRIVATE cxx_std_20)
|
|
freepdfeditor_apply_warnings(spike_b_reconstruction)
|
|
freepdfeditor_apply_hardening(spike_b_reconstruction)
|
|
|
|
# --- Spike B step 1: glyph→Unicode via ToUnicode + cmap fallback (§4.1 step 1) ---
|
|
# Exercises the glyph→Unicode priority ladder on a real embedded font: parse
|
|
# the ToUnicode CMap via QPDF (step 1), fall back to the embedded font's cmap
|
|
# via FreeType (step 4). The highest-risk reconstruction step, not covered by
|
|
# Spike B's synthetic corpus. Reuses the QPDF and FreeType targets found above
|
|
# (Spike A's QPDF, Spike C's FreeType).
|
|
if(TARGET PkgConfig::QPDF AND TARGET PkgConfig::FREETYPE)
|
|
add_executable(spike_b1_glyph_unicode
|
|
common/SpikeRunner.cpp
|
|
common/SpikeRunner.h
|
|
B1_glyph_unicode/main.cpp
|
|
B1_glyph_unicode/GlyphUnicode.cpp
|
|
B1_glyph_unicode/GlyphUnicode.h
|
|
)
|
|
target_include_directories(spike_b1_glyph_unicode PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
target_link_libraries(spike_b1_glyph_unicode PRIVATE
|
|
${_fpe_qpdf_target} PkgConfig::FREETYPE)
|
|
target_compile_features(spike_b1_glyph_unicode PRIVATE cxx_std_20)
|
|
freepdfeditor_apply_warnings(spike_b1_glyph_unicode)
|
|
freepdfeditor_apply_hardening(spike_b1_glyph_unicode)
|
|
endif()
|
|
|
|
# --- Spike C: hb-subset growth of an embedded subset font (§14 step 6) ---
|
|
# Grow an existing subset font with a new glyph using hb-subset and verify the
|
|
# result renders via FreeType. §4.2 resolution ladder step 1: when the user
|
|
# types a character not in the embedded subset, grow the subset from the
|
|
# installed full font and embed the new subset (never mutating the original).
|
|
find_package(PkgConfig QUIET)
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(HARFBUZZ harfbuzz harfbuzz-subset IMPORTED_TARGET)
|
|
endif()
|
|
|
|
if(TARGET PkgConfig::HARFBUZZ AND TARGET PkgConfig::FREETYPE)
|
|
add_executable(spike_c_subset_growth
|
|
common/SpikeRunner.cpp
|
|
common/SpikeRunner.h
|
|
C_subset_growth/main.cpp
|
|
C_subset_growth/SubsetGrowth.cpp
|
|
C_subset_growth/SubsetGrowth.h
|
|
)
|
|
target_include_directories(spike_c_subset_growth PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
target_link_libraries(spike_c_subset_growth PRIVATE PkgConfig::HARFBUZZ PkgConfig::FREETYPE)
|
|
target_compile_features(spike_c_subset_growth PRIVATE cxx_std_20)
|
|
freepdfeditor_apply_warnings(spike_c_subset_growth)
|
|
freepdfeditor_apply_hardening(spike_c_subset_growth)
|
|
else()
|
|
message(STATUS
|
|
"HarfBuzz/FreeType not found — Spike C (subset growth) will not be "
|
|
"built. Install libharfbuzz-dev and libfreetype-dev to enable it.")
|
|
endif()
|
|
|
|
# --- Spike E: sandbox + IPC bring-up (§14 step 8) ---
|
|
# Two-process model (ADR-0004): a sandboxed document process (seccomp-bpf) and
|
|
# a UI process, talking over a socketpair via a length-prefixed binary IPC.
|
|
# This is the one thing the plan says is genuinely painful to retrofit, so it
|
|
# is de-risked at M0. Linux-only at this stage (seccomp-bpf); macOS App Sandbox
|
|
# and Windows AppContainer land in M1.
|
|
#
|
|
# An earlier version used Cap'n Proto two-party RPC over the socketpair; the
|
|
# server received and processed requests but the responses never reached the
|
|
# client — a real integration issue recorded in the spike result doc for M2 to
|
|
# debug with the full event-loop integration. The raw length-prefixed protocol
|
|
# measures the channel cost without that blocker. The Cap'n Proto schema
|
|
# (ipc.capnp) is kept for the M2 RPC work.
|
|
find_package(PkgConfig QUIET)
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(SECCOMP libseccomp IMPORTED_TARGET)
|
|
endif()
|
|
|
|
if(TARGET PkgConfig::SECCOMP)
|
|
add_executable(spike_e_sandbox
|
|
common/SpikeRunner.cpp
|
|
common/SpikeRunner.h
|
|
E_sandbox/main.cpp
|
|
E_sandbox/Sandbox.cpp
|
|
E_sandbox/Sandbox.h
|
|
E_sandbox/DocumentProcess.cpp
|
|
E_sandbox/DocumentProcess.h
|
|
E_sandbox/UIProcess.cpp
|
|
E_sandbox/UIProcess.h
|
|
)
|
|
target_include_directories(spike_e_sandbox PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
target_link_libraries(spike_e_sandbox PRIVATE PkgConfig::SECCOMP)
|
|
target_compile_features(spike_e_sandbox PRIVATE cxx_std_20)
|
|
freepdfeditor_apply_warnings(spike_e_sandbox)
|
|
freepdfeditor_apply_hardening(spike_e_sandbox)
|
|
else()
|
|
message(STATUS
|
|
"libseccomp not found — Spike E (sandbox) will not be built. "
|
|
"Install libseccomp-dev to enable it.")
|
|
endif() |