first commit

This commit is contained in:
Furqan-14
2026-05-15 10:39:16 +05:30
commit 43eba01201
38 changed files with 2021 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
# PDFium — built from source
PDFium is the parser + base-rendering core of the engine (Rule R1). It is **not**
a vcpkg package; Google ships it only as source built with their own toolchain
(**depot_tools + GN + Ninja**). The timeline flags this as *"the single biggest
Day-1 risk — budget a full day for depot_tools quirks."*
## What the build scripts do
`build_pdfium.ps1` (Windows) and `build_pdfium.sh` (Linux/macOS) automate:
1. Read the **pinned revision** from `pdfium.pinned` (refuses to run if it is
still the placeholder — Rule: never track rolling HEAD).
2. Clone `depot_tools` under the **build root** and run its Windows bootstrap
(fetches bundled git + python via CIPD).
3. `gclient config` + `gclient sync` the PDFium tree into `<build root>/checkout/`.
4. Check out the exact pinned commit and re-sync its DEPS.
5. Write `args.gn` for a **static, standalone, monolithic, embed-friendly** build:
- `is_component_build = false` — one static lib, not many DLLs
- `pdf_is_standalone = true`
- `pdf_enable_v8 = false`, `pdf_enable_xfa = false` — no JS / XFA in v1
- `pdf_use_skia = false` — we drive Skia ourselves later
- `use_custom_libcxx = false` — link the system C++ runtime so PDFium is
ABI-compatible with the rest of the engine *(critical for embedding)*
- `pdf_use_partition_alloc = false`
6. `gn gen` + `ninja -C out/Release pdfium`.
7. Copy `public/*.h``install/include/` and the static lib → `install/lib/`.
`cmake/pdfium.cmake` then turns `install/` into the `pdfium::pdfium` imported
target. Build the engine with `-DPDFENGINE_WITH_PDFIUM=ON` to link it.
## The build root — paths with spaces
**depot_tools, GN and Ninja do not support a space anywhere in their own path.**
By default the scripts build under this directory (`third_party/pdfium/`), which
is fine when the repo lives on a space-free path.
If the repo path contains a space (e.g. `OneDrive\...\PDF Editor\...`), the
scripts **hard-error** and you must point the build root somewhere space-free:
```powershell
# Windows
$env:PDFIUM_BUILD_ROOT = 'C:\pdfium-build'
pwsh third_party\pdfium\build_pdfium.ps1
```
```sh
# Linux / macOS
PDFIUM_BUILD_ROOT=/tmp/pdfium-build ./third_party/pdfium/build_pdfium.sh
```
`depot_tools/` and `checkout/` then live under the build root; the finished
`install/` is **always** written into `third_party/pdfium/install/` (git-ignored)
so `cmake/pdfium.cmake` finds it in the same place regardless.
## Pinning the revision
`pdfium.pinned` holds the pinned commit SHA. It is currently pinned to a
specific `main`-branch commit. To re-pin (a deliberate, scheduled action — the
risk register calls for *quarterly* rebases):
1. Pick a commit from https://pdfium.googlesource.com/pdfium/+log/main (or the
tip of a recent `chromium/NNNN` release branch).
2. Update `PDFIUM_COMMIT=` in `pdfium.pinned` and commit it.
3. Re-run the build script.
## Usage
Prerequisites: Git, Python 3, and a C++ toolchain (Windows: Visual Studio 2022+
with the "Desktop development with C++" workload).
```powershell
# Windows — set PDFIUM_BUILD_ROOT first if the repo path has a space (see above)
pwsh third_party\pdfium\build_pdfium.ps1
```
```sh
# Linux / macOS
./third_party/pdfium/build_pdfium.sh
```
Expect the first run to take a long time — the `gclient sync` alone pulls
several GB, and the compile is lengthy. `depot_tools/`, `checkout/`, and
`install/` are all git-ignored.
## Troubleshooting
- **`'C:\...\PDF' is not recognized` / GN or Ninja path errors** — a space in
the build-root path. Set `PDFIUM_BUILD_ROOT` to a space-free location.
- **`gclient sync` aborts with "uncommitted changes"** — git's `core.autocrlf`
rewrote a dependency checkout. The scripts already inject `core.autocrlf=false`
per-process; if you bypass them, set it yourself.
- **depot_tools `git`/`python` not found** — depot_tools was not bootstrapped.
The scripts run `bootstrap\win_tools.bat`; do not set `DEPOT_TOOLS_UPDATE=0`,
which suppresses that bootstrap.
+37
View File
@@ -0,0 +1,37 @@
# GN build args for PDFium — static, standalone, monolithic, embed-friendly.
# Copied to out/Release/args.gn by the build scripts. See README.md for rationale.
is_debug = false
# One self-contained static library, not a component (DLL) build.
is_component_build = false
# Bundle PDFium *and all its dependencies* into a single static lib
# (out/Release/obj/pdfium.lib). Without this the `pdfium` target is just a
# GN group — it builds the component libs but never archives them together,
# leaving nothing for the engine to link against.
pdf_is_complete_lib = true
# Standalone embedder build (no full Chromium tree).
pdf_is_standalone = true
# v1 scope: no JavaScript engine, no XFA forms.
pdf_enable_v8 = false
pdf_enable_xfa = false
# We integrate Skia ourselves at the engine layer — PDFium uses its built-in
# AGG rasterizer here.
pdf_use_skia = false
# Critical for embedding: link the system C++ runtime instead of Chromium's
# bundled libc++, so PDFium is ABI-compatible with the rest of the engine.
use_custom_libcxx = false
# Avoid Chromium's PartitionAlloc — keeps the embed surface simple.
pdf_use_partition_alloc = false
# Don't require the Chromium clang plugins for a standalone build.
clang_use_chrome_plugins = false
# Treat warnings as warnings — PDFium upstream, not our code.
treat_warnings_as_errors = false
+144
View File
@@ -0,0 +1,144 @@
#requires -Version 5.1
# Build PDFium from source (Windows) into third_party\pdfium\install\.
#
# depot_tools, the PDFium checkout, and the GN/Ninja build all happen under a
# BUILD ROOT. depot_tools, GN and Ninja do NOT support spaces anywhere in their
# own path. If this repo lives under a path containing a space (for example
# OneDrive\...\PDF Editor\...), you MUST point the build root somewhere
# space-free:
#
# $env:PDFIUM_BUILD_ROOT = 'C:\pdfium-build'
# pwsh third_party\pdfium\build_pdfium.ps1
#
# The finished static lib + public headers are always installed into
# third_party\pdfium\install\ (git-ignored) regardless of the build root, so
# cmake/pdfium.cmake finds them in the same place either way.
#
# One-time and slow: a multi-GB gclient sync plus a long compile. See README.md.
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Install = Join-Path $ScriptDir 'install'
$PinnedFile = Join-Path $ScriptDir 'pdfium.pinned'
# Build root: depot_tools + the checkout live here. Defaults to this directory
# (fine for repos on a space-free path), but MUST be overridden to a space-free
# location otherwise.
$BuildRoot = if ($env:PDFIUM_BUILD_ROOT) { $env:PDFIUM_BUILD_ROOT } else { $ScriptDir }
if ($BuildRoot -match '\s') {
Write-Error @"
PDFium build root contains a space: $BuildRoot
depot_tools, GN and Ninja cannot build under a path with spaces. Set a
space-free build root and re-run, e.g.:
`$env:PDFIUM_BUILD_ROOT = 'C:\pdfium-build'
pwsh third_party\pdfium\build_pdfium.ps1
"@
}
$DepotTools = Join-Path $BuildRoot 'depot_tools'
$Checkout = Join-Path $BuildRoot 'checkout'
Write-Host ">> Build root: $BuildRoot"
# --- 1. Read and validate the pinned revision -------------------------------
$pinned = Get-Content $PinnedFile | Where-Object { $_ -match '^\s*PDFIUM_' }
$repo = ($pinned | Where-Object { $_ -match '^PDFIUM_REPO=' }) -replace '^PDFIUM_REPO=', ''
$commit = ($pinned | Where-Object { $_ -match '^PDFIUM_COMMIT=' }) -replace '^PDFIUM_COMMIT=', ''
if (-not $commit -or $commit -eq 'REPLACE_WITH_PINNED_COMMIT_SHA') {
Write-Error 'PDFium revision is not pinned. Edit pdfium.pinned first (see README.md).'
}
Write-Host ">> PDFium pinned at $commit"
# --- 2. depot_tools ---------------------------------------------------------
New-Item -ItemType Directory -Force -Path $BuildRoot | Out-Null
if (-not (Test-Path $DepotTools)) {
Write-Host '>> Cloning depot_tools'
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git $DepotTools
}
$env:PATH = "$DepotTools;$env:PATH"
# Use the locally installed Visual Studio toolchain, not Google's internal one.
$env:DEPOT_TOOLS_WIN_TOOLCHAIN = '0'
# Git settings Chromium requires on Windows, injected per-process via GIT_CONFIG_*
# so the user's global git config is never touched. core.autocrlf=false is the
# critical one: without it, gclient sees CRLF-converted dependency checkouts as
# "uncommitted changes" and aborts the sync.
$env:GIT_CONFIG_COUNT = '4'
$env:GIT_CONFIG_KEY_0 = 'core.autocrlf'; $env:GIT_CONFIG_VALUE_0 = 'false'
$env:GIT_CONFIG_KEY_1 = 'core.filemode'; $env:GIT_CONFIG_VALUE_1 = 'false'
$env:GIT_CONFIG_KEY_2 = 'core.fscache'; $env:GIT_CONFIG_VALUE_2 = 'true'
$env:GIT_CONFIG_KEY_3 = 'core.preloadindex'; $env:GIT_CONFIG_VALUE_3 = 'true'
# Bootstrap depot_tools. On Windows it must fetch its bundled git + python via
# CIPD and generate the git.bat / python3.bat wrappers before gclient can run.
# NOTE: do NOT set DEPOT_TOOLS_UPDATE=0 here — that suppresses this initial
# bootstrap, not just self-updates. Reproducibility comes from the pinned PDFium
# revision; depot_tools itself is designed to self-manage.
Write-Host '>> Bootstrapping depot_tools (fetches bundled git + python; one-time, slow)'
& cmd /c "`"$DepotTools\bootstrap\win_tools.bat`""
if ($LASTEXITCODE -ne 0) { Write-Error 'depot_tools bootstrap failed.' }
# --- 2b. Locate Visual Studio for the GN build -----------------------------
# gn's vs_toolchain.py finds VS via the vs<YEAR>_install env var or a fixed
# path (...\Microsoft Visual Studio\<YEAR>). VS *Build Tools* installs under a
# major-version path (e.g. \18\BuildTools), not the year, so the fixed-path
# probe misses it — resolve VS with vswhere and set vs<YEAR>_install. vswhere
# needs `-products *` to see Build Tools at all.
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
if (-not (Test-Path $vswhere)) {
Write-Error 'vswhere.exe not found. Install Visual Studio 2022+ (or Build Tools) with the C++ workload.'
}
$vsPath = (& $vswhere -latest -prerelease -products * -property installationPath | Select-Object -First 1)
$vsVer = (& $vswhere -latest -prerelease -products * -property installationVersion | Select-Object -First 1)
if (-not $vsPath -or -not (Test-Path (Join-Path $vsPath 'VC\Tools\MSVC'))) {
Write-Error 'No Visual Studio with the C++ toolchain (VC.Tools) found — install the "Desktop development with C++" workload.'
}
$vsYear = @{ '18' = '2026'; '17' = '2022'; '16' = '2019'; '15' = '2017' }[$vsVer.Split('.')[0]]
if (-not $vsYear) { Write-Error "Unsupported Visual Studio major version: $vsVer (need 15/16/17/18)." }
Write-Host ">> Visual Studio ${vsYear}: $vsPath"
Set-Item -Path "env:vs${vsYear}_install" -Value $vsPath
$env:GYP_MSVS_VERSION = $vsYear
# --- 3. Fetch / sync the PDFium tree ----------------------------------------
New-Item -ItemType Directory -Force -Path $Checkout | Out-Null
Push-Location $Checkout
if (-not (Test-Path (Join-Path $Checkout 'pdfium'))) {
Write-Host '>> gclient config (unmanaged)'
& gclient config --unmanaged $repo
if ($LASTEXITCODE -ne 0) { Write-Error 'gclient config failed.' }
}
Write-Host '>> gclient sync (pulls several GB; slow)'
& gclient sync --no-history --shallow --reset --force
if ($LASTEXITCODE -ne 0) { Write-Error 'gclient sync failed.' }
# --- 4. Pin to the exact commit + sync its DEPS -----------------------------
Push-Location (Join-Path $Checkout 'pdfium')
& git fetch origin $commit
& git checkout --detach $commit
if ($LASTEXITCODE -ne 0) { Write-Error "git checkout $commit failed." }
& gclient sync --no-history --shallow --reset --force -D
if ($LASTEXITCODE -ne 0) { Write-Error 'gclient sync (pinned DEPS) failed.' }
# --- 5. GN args: static, standalone, monolithic, embed-friendly -------------
New-Item -ItemType Directory -Force -Path 'out\Release' | Out-Null
Copy-Item (Join-Path $ScriptDir 'args.gn') 'out\Release\args.gn' -Force
# --- 6. Generate + build ----------------------------------------------------
Write-Host '>> gn gen'
& gn gen out/Release
if ($LASTEXITCODE -ne 0) { Write-Error 'gn gen failed.' }
Write-Host '>> ninja (long compile)'
& ninja -C out/Release pdfium
if ($LASTEXITCODE -ne 0) { Write-Error 'ninja build failed.' }
# --- 7. Install: public headers + static lib --------------------------------
Write-Host ">> Installing into $Install"
if (Test-Path $Install) { Remove-Item -Recurse -Force $Install }
New-Item -ItemType Directory -Force -Path "$Install\include", "$Install\lib" | Out-Null
Copy-Item 'public\*.h' "$Install\include\" -Force
if (Test-Path 'public\cpp') { Copy-Item 'public\cpp' "$Install\include\" -Recurse -Force }
$lib = if (Test-Path 'out\Release\obj\pdfium.lib') { 'out\Release\obj\pdfium.lib' }
else { 'out\Release\pdfium.lib' }
Copy-Item $lib "$Install\lib\" -Force
Pop-Location
Pop-Location
Write-Host '>> Done. Configure the engine with -DPDFENGINE_WITH_PDFIUM=ON'
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# Build PDFium from source (Linux / macOS) into third_party/pdfium/install/.
#
# depot_tools, the PDFium checkout, and the GN/Ninja build all happen under a
# BUILD ROOT. depot_tools, GN and Ninja do NOT support spaces anywhere in their
# own path. If this repo lives under a path containing a space, you MUST point
# the build root somewhere space-free:
#
# PDFIUM_BUILD_ROOT=/tmp/pdfium-build ./third_party/pdfium/build_pdfium.sh
#
# The finished static lib + public headers are always installed into
# third_party/pdfium/install/ (git-ignored) regardless of the build root, so
# cmake/pdfium.cmake finds them in the same place either way.
#
# One-time and slow: a multi-GB gclient sync plus a long compile. See README.md.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="${SCRIPT_DIR}/install"
PINNED_FILE="${SCRIPT_DIR}/pdfium.pinned"
# Build root: depot_tools + the checkout live here. Defaults to this directory
# (fine for repos on a space-free path), but MUST be overridden otherwise.
BUILD_ROOT="${PDFIUM_BUILD_ROOT:-${SCRIPT_DIR}}"
case "${BUILD_ROOT}" in
*' '*)
echo "ERROR: PDFium build root contains a space: ${BUILD_ROOT}" >&2
echo "depot_tools, GN and Ninja cannot build under a path with spaces." >&2
echo "Re-run with a space-free build root, e.g.:" >&2
echo " PDFIUM_BUILD_ROOT=/tmp/pdfium-build $0" >&2
exit 1 ;;
esac
DEPOT_TOOLS_DIR="${BUILD_ROOT}/depot_tools"
CHECKOUT_DIR="${BUILD_ROOT}/checkout"
echo ">> Build root: ${BUILD_ROOT}"
# --- 1. Read and validate the pinned revision -------------------------------
PDFIUM_REPO="$(grep -E '^PDFIUM_REPO=' "${PINNED_FILE}" | cut -d= -f2-)"
PDFIUM_COMMIT="$(grep -E '^PDFIUM_COMMIT=' "${PINNED_FILE}" | cut -d= -f2-)"
if [[ -z "${PDFIUM_COMMIT}" || "${PDFIUM_COMMIT}" == "REPLACE_WITH_PINNED_COMMIT_SHA" ]]; then
echo "ERROR: PDFium revision is not pinned. Edit pdfium.pinned first (see README.md)." >&2
exit 1
fi
echo ">> PDFium pinned at ${PDFIUM_COMMIT}"
# --- 2. depot_tools ---------------------------------------------------------
mkdir -p "${BUILD_ROOT}"
if [[ ! -d "${DEPOT_TOOLS_DIR}" ]]; then
echo ">> Cloning depot_tools"
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git \
"${DEPOT_TOOLS_DIR}"
fi
export PATH="${DEPOT_TOOLS_DIR}:${PATH}"
# Do NOT set DEPOT_TOOLS_UPDATE=0 — depot_tools is designed to self-manage, and
# on first use it must bootstrap. Reproducibility comes from the pinned PDFium
# revision below, not from freezing depot_tools.
# Git settings injected per-process via GIT_CONFIG_* so the user's global git
# config is never touched. core.autocrlf=false avoids gclient seeing dependency
# checkouts as "uncommitted changes" on platforms where autocrlf is enabled.
export GIT_CONFIG_COUNT=2
export GIT_CONFIG_KEY_0=core.autocrlf GIT_CONFIG_VALUE_0=false
export GIT_CONFIG_KEY_1=core.filemode GIT_CONFIG_VALUE_1=false
# --- 3. Fetch / sync the PDFium tree ----------------------------------------
mkdir -p "${CHECKOUT_DIR}"
cd "${CHECKOUT_DIR}"
if [[ ! -d "${CHECKOUT_DIR}/pdfium" ]]; then
echo ">> gclient config (unmanaged)"
gclient config --unmanaged "${PDFIUM_REPO}"
fi
echo ">> gclient sync (pulls several GB; slow)"
gclient sync --no-history --shallow --reset --force
# --- 4. Pin to the exact commit + sync its DEPS -----------------------------
cd "${CHECKOUT_DIR}/pdfium"
git fetch origin "${PDFIUM_COMMIT}"
git checkout --detach "${PDFIUM_COMMIT}"
gclient sync --no-history --shallow --reset --force -D
# --- 5. GN args: static, standalone, monolithic, embed-friendly -------------
mkdir -p out/Release
cp "${SCRIPT_DIR}/args.gn" out/Release/args.gn
# --- 6. Generate + build ----------------------------------------------------
echo ">> gn gen + ninja"
gn gen out/Release
ninja -C out/Release pdfium
# --- 7. Install: public headers + static lib --------------------------------
echo ">> Installing into ${INSTALL_DIR}"
rm -rf "${INSTALL_DIR}"
mkdir -p "${INSTALL_DIR}/include" "${INSTALL_DIR}/lib"
cp public/*.h "${INSTALL_DIR}/include/"
cp -r public/cpp "${INSTALL_DIR}/include/" 2>/dev/null || true
if [[ -f out/Release/obj/libpdfium.a ]]; then
cp out/Release/obj/libpdfium.a "${INSTALL_DIR}/lib/"
else
# Fallback: some configurations emit the lib at the out-dir root.
cp out/Release/libpdfium.a "${INSTALL_DIR}/lib/"
fi
echo ">> Done. Configure the engine with -DPDFENGINE_WITH_PDFIUM=ON"
+13
View File
@@ -0,0 +1,13 @@
# PDFium pinned revision — Rule: never track rolling HEAD.
#
# Pinned to a specific main-branch commit (a clean dependency-roll commit).
# Rebasing is a deliberate, scheduled (quarterly) action — bump the SHA below,
# commit it, and re-run the build scripts.
#
# To re-pin: pick a commit from https://pdfium.googlesource.com/pdfium/+log/main
# (or the tip of a recent chromium/NNNN release branch) and update PDFIUM_COMMIT.
# The build scripts refuse to run while PDFIUM_COMMIT is the placeholder string.
PDFIUM_REPO=https://pdfium.googlesource.com/pdfium.git
# main @ 2026-05-13 — "Roll third_party/cpu_features/src/ ..."
PDFIUM_COMMIT=423b6b376015e9458d588bd9a8f7b5c4ae21f8a2