1{
2 stdenv,
3 lib,
4 pkgs,
5 buildPythonPackage,
6 fetchFromGitHub,
7 fetchgit,
8 setuptools-scm,
9 pdfium-binaries,
10 numpy,
11 pillow,
12 pytestCheckHook,
13 removeReferencesTo,
14 python,
15 replaceVars,
16}:
17
18let
19 pdfiumVersion = "${pdfium-binaries.version}";
20
21 headers = fetchgit {
22 url = "https://pdfium.googlesource.com/pdfium";
23 # The latest revision on the chromium/${pdfiumVersion} branch
24 rev = "9232d7c94a0007377a8034222f47683fe391d474";
25 hash = "sha256-dI3jTyVYc0EmMLHTiVjGSf3C2noS9Ru5WijEJFtiSFk=";
26 sparseCheckout = [
27 "public"
28 ];
29 };
30
31 # They demand their own fork of ctypesgen
32 ctypesgen = buildPythonPackage rec {
33 pname = "ctypesgen";
34 version = "1.1.1+g${src.rev}"; # the most recent tag + git version
35 pyproject = true;
36
37 src = fetchFromGitHub {
38 owner = "pypdfium2-team";
39 repo = "ctypesgen";
40 rev = "848e9fbb1374f7f58a7ebf5e5da5c33292480b30";
41 hash = "sha256-3JA7cW/xaEj/DxMHEypROwrKGo7EwUEcipRqALTvydw=";
42 };
43
44 patches = [
45 (replaceVars ./fix-cc-detection.patch {
46 cc = "${stdenv.cc.targetPrefix}cc";
47 })
48 ];
49
50 build-system = [
51 setuptools-scm
52 ];
53
54 env.SETUPTOOLS_SCM_PRETEND_VERSION = "${version}";
55 };
56
57in
58buildPythonPackage rec {
59 pname = "pypdfium2";
60 version = "4.30.1";
61 pyproject = true;
62
63 src = fetchFromGitHub {
64 owner = "pypdfium2-team";
65 repo = "pypdfium2";
66 tag = version;
67 hash = "sha256-v8f/XruGJYK3H9z4Q1rLg4fEnPHa8tTOlNTBMVxPEgA=";
68 };
69
70 build-system = [
71 ctypesgen
72 setuptools-scm
73 ];
74
75 nativeBuildInputs = [
76 removeReferencesTo
77 ];
78
79 propagatedBuildInputs = [
80 pdfium-binaries
81 ];
82
83 # Build system insists on fetching from the internet unless "cached" files
84 # are prepared. Even then, some code patching needs to happen to make it not
85 # talk to the internet.
86
87 # The project doesn't seem very open to allow for offline building either,
88 # see: https://github.com/pypdfium2-team/pypdfium2/discussions/274
89 preBuild =
90 let
91 pdfiumLib = lib.makeLibraryPath [ pdfium-binaries ];
92 inputVersionFile = (pkgs.formats.json { }).generate "version.json" {
93 version = lib.strings.toInt pdfiumVersion;
94 source = "generated";
95 flags = [ ];
96 run_lds = [ pdfiumLib ];
97 guard_symbols = false;
98 };
99 bindingsDir = "data/bindings";
100 headersDir = "${bindingsDir}/headers";
101 versionFile = "${bindingsDir}/version.json";
102 in
103 ''
104 # Preseed the headers and version file
105 mkdir -p ${bindingsDir}
106 cp -r ${headers}/public ${headersDir}
107 install -m 644 ${inputVersionFile} ${versionFile}
108
109 # Make generated bindings consider pdfium derivation path when loading dynamic libraries
110 substituteInPlace setupsrc/pypdfium2_setup/emplace.py \
111 --replace-fail 'build_pdfium_bindings(pdfium_ver, flags=flags, guard_symbols=True, run_lds=[])' \
112 'build_pdfium_bindings(pdfium_ver, flags=flags, guard_symbols=True, run_lds=["${pdfiumLib}"])'
113
114 # Short circuit the version pull from the internet
115 substituteInPlace setupsrc/pypdfium2_setup/packaging_base.py \
116 --replace-fail 'PdfiumVer.to_full(build)._asdict()' \
117 '{"major": 133, "minor": 0, "build": ${pdfiumVersion}, "patch": 1}'
118 '';
119 env.PDFIUM_PLATFORM = "system:${pdfiumVersion}";
120
121 # Remove references to stdenv in comments.
122 postInstall = ''
123 remove-references-to -t ${stdenv.cc.cc} $out/${python.sitePackages}/pypdfium2_raw/bindings.py
124 '';
125
126 nativeCheckInputs = [
127 numpy
128 pillow
129 pytestCheckHook
130 ];
131
132 pythonImportsCheck = [
133 "pypdfium2"
134 ];
135
136 meta = {
137 changelog = "https://github.com/pypdfium2-team/pypdfium2/releases/tag/${version}";
138 description = "Python bindings to PDFium";
139 homepage = "https://pypdfium2.readthedocs.io/";
140 license = with lib.licenses; [
141 asl20 # or
142 mit
143 ];
144 maintainers = with lib.maintainers; [ booxter ];
145 };
146}