Skip to content

Commit 7a286f7

Browse files
Improved building for Python stable ABI / limited API.
setup.py: Renamed PYMUPDF_SETUP_Py_LIMITED_API to all-caps PYMUPDF_SETUP_PY_LIMITED_API; accept only '0 or '1' instead of an actual value; pass True (not '0x03080000') to pipcl if '1'. Use pipcl.current_py_limited_api() to get Py_LIMITED_API value suitable for current Python version. .github/workflows/build_wheels.yml: Use PYMUPDF_SETUP_PY_LIMITED_API. scripts/gh_release.py Use PYMUPDF_SETUP_PY_LIMITED_API.
1 parent bce515c commit 7a286f7

File tree

3 files changed

+34
-40
lines changed

3 files changed

+34
-40
lines changed

.github/workflows/build_wheels.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ on:
4848
# default: '-'
4949
# We can't currently have more than 10 inputs
5050

51-
PYMUPDF_SETUP_Py_LIMITED_API:
51+
PYMUPDF_SETUP_PY_LIMITED_API:
5252
description: 'If not "", is used to build single wheel for each OS.'
5353
type: string
5454
default: ''
@@ -147,7 +147,7 @@ jobs:
147147

148148
inputs_wheels_cps: ${{inputs.wheels_cps}}
149149

150-
PYMUPDF_SETUP_Py_LIMITED_API: ${{inputs.PYMUPDF_SETUP_Py_LIMITED_API}}
150+
PYMUPDF_SETUP_PY_LIMITED_API: ${{inputs.PYMUPDF_SETUP_PY_LIMITED_API}}
151151

152152
run:
153153
python scripts/gh_release.py

scripts/gh_release.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def get_bool(name, default=0):
200200
inputs_PYMUPDF_SETUP_MUPDF_BUILD = os.environ.get('inputs_PYMUPDF_SETUP_MUPDF_BUILD')
201201
inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE = os.environ.get('inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE')
202202

203-
PYMUPDF_SETUP_Py_LIMITED_API = os.environ.get('PYMUPDF_SETUP_Py_LIMITED_API')
203+
PYMUPDF_SETUP_PY_LIMITED_API = os.environ.get('PYMUPDF_SETUP_PY_LIMITED_API')
204204

205205
log( f'{inputs_flavours=}')
206206
log( f'{inputs_sdist=}')
@@ -215,7 +215,7 @@ def get_bool(name, default=0):
215215
log( f'{inputs_wheels_cps=}')
216216
log( f'{inputs_PYMUPDF_SETUP_MUPDF_BUILD=}')
217217
log( f'{inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE=}')
218-
log( f'{PYMUPDF_SETUP_Py_LIMITED_API=}')
218+
log( f'{PYMUPDF_SETUP_PY_LIMITED_API=}')
219219

220220
# Build Pyodide wheel if specified.
221221
#
@@ -384,14 +384,14 @@ def set_cibuild_test():
384384
# We include MuPDF build-time files.
385385
flavour_d = True
386386

387-
if PYMUPDF_SETUP_Py_LIMITED_API:
387+
if PYMUPDF_SETUP_PY_LIMITED_API:
388388
# Build one wheel with oldest python, then fake build with other python
389389
# versions so we test everything.
390-
log(f'{PYMUPDF_SETUP_Py_LIMITED_API=}')
391-
env_pass('PYMUPDF_SETUP_Py_LIMITED_API')
392-
# This isn't actually necessary - PYMUPDF_SETUP_Py_LIMITED_API is
390+
log(f'{PYMUPDF_SETUP_PY_LIMITED_API=}')
391+
env_pass('PYMUPDF_SETUP_PY_LIMITED_API')
392+
# This isn't actually necessary - PYMUPDF_SETUP_PY_LIMITED_API is
393393
# already in the environment - but we set it anyway for clarity.
394-
env_set('PYMUPDF_SETUP_Py_LIMITED_API', PYMUPDF_SETUP_Py_LIMITED_API, pass_=1)
394+
env_set('PYMUPDF_SETUP_PY_LIMITED_API', PYMUPDF_SETUP_PY_LIMITED_API, pass_=1)
395395
CIBW_BUILD_old = env_extra.get('CIBW_BUILD')
396396
assert CIBW_BUILD_old is not None
397397
env_set('CIBW_BUILD', 'cp38*')

setup.py

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,8 @@
149149
PYMUPDF_SETUP_MUPDF_REBUILD
150150
If 0 we do not (re)build mupdf.
151151
152-
PYMUPDF_SETUP_Py_LIMITED_API
153-
None, 'default' or the value of `Py_LIMITED_API` macro when building
154-
MuPDF and PyMuPDF Python client code. If 'defaut', we use hard-coded
155-
default.
156-
157-
This will hopefully allow the same build of PyMuPDF to be used with
158-
multiple Python versions.
152+
PYMUPDF_SETUP_PY_LIMITED_API
153+
If '1', we build for current Python's stable ABI.
159154
160155
PYMUPDF_SETUP_URL_WHEEL
161156
If set, we use an existing wheel instead of building a new wheel.
@@ -240,9 +235,10 @@ def log( text):
240235
# Name of file that identifies that we are in a PyMuPDF sdist.
241236
g_pymupdfb_sdist_marker = 'pymupdfb_sdist'
242237

243-
Py_LIMITED_API = os.environ.get('PYMUPDF_SETUP_Py_LIMITED_API')
244-
if Py_LIMITED_API == 'default':
245-
Py_LIMITED_API = '0x03080000'
238+
PYMUPDF_SETUP_PY_LIMITED_API = os.environ.get('PYMUPDF_SETUP_PY_LIMITED_API')
239+
assert PYMUPDF_SETUP_PY_LIMITED_API in (None, '0', '1'), \
240+
f'Should be "0", "1" or undefined: {PYMUPDF_SETUP_PY_LIMITED_API=}.'
241+
g_py_limited_api = (PYMUPDF_SETUP_PY_LIMITED_API == '1')
246242

247243
PYMUPDF_SETUP_URL_WHEEL = os.environ.get('PYMUPDF_SETUP_URL_WHEEL')
248244
log(f'{PYMUPDF_SETUP_URL_WHEEL=}')
@@ -570,7 +566,7 @@ def build():
570566
mupdf_local,
571567
build_type,
572568
overwrite_config,
573-
Py_LIMITED_API,
569+
g_py_limited_api,
574570
PYMUPDF_SETUP_MUPDF_REFCHECK_IF,
575571
PYMUPDF_SETUP_MUPDF_TRACE_IF,
576572
)
@@ -584,7 +580,7 @@ def build():
584580
mupdf_local,
585581
build_type,
586582
overwrite_config,
587-
Py_LIMITED_API,
583+
g_py_limited_api,
588584
PYMUPDF_SETUP_MUPDF_REFCHECK_IF,
589585
PYMUPDF_SETUP_MUPDF_TRACE_IF,
590586
)
@@ -597,7 +593,7 @@ def build():
597593
mupdf_local,
598594
mupdf_build_dir,
599595
build_type,
600-
Py_LIMITED_API,
596+
g_py_limited_api,
601597
)
602598
else:
603599
log(f'Not building extension.')
@@ -711,7 +707,7 @@ def build_mupdf_windows(
711707
mupdf_local,
712708
build_type,
713709
overwrite_config,
714-
Py_LIMITED_API,
710+
g_py_limited_api,
715711
PYMUPDF_SETUP_MUPDF_REFCHECK_IF,
716712
PYMUPDF_SETUP_MUPDF_TRACE_IF,
717713
):
@@ -736,8 +732,8 @@ def build_mupdf_windows(
736732
wp = pipcl.wdev.WindowsPython()
737733
tesseract = '' if os.environ.get('PYMUPDF_SETUP_MUPDF_TESSERACT') == '0' else 'tesseract-'
738734
windows_build_tail = f'build\\shared-{tesseract}{build_type}'
739-
if Py_LIMITED_API:
740-
windows_build_tail += f'-Py_LIMITED_API={Py_LIMITED_API}'
735+
if g_py_limited_api:
736+
windows_build_tail += f'-Py_LIMITED_API={pipcl.current_py_limited_api()}'
741737
windows_build_tail += f'-x{wp.cpu.bits}-py{wp.version}'
742738
windows_build_dir = f'{mupdf_local}\\{windows_build_tail}'
743739
#log( f'Building mupdf.')
@@ -805,7 +801,7 @@ def build_mupdf_unix(
805801
mupdf_local,
806802
build_type,
807803
overwrite_config,
808-
Py_LIMITED_API,
804+
g_py_limited_api,
809805
PYMUPDF_SETUP_MUPDF_REFCHECK_IF,
810806
PYMUPDF_SETUP_MUPDF_TRACE_IF,
811807
):
@@ -880,9 +876,9 @@ def build_mupdf_unix(
880876
):
881877
log(f'Appending `bsymbolic-` to MuPDF build path.')
882878
build_prefix += 'bsymbolic-'
883-
log(f'{Py_LIMITED_API=}')
884-
if Py_LIMITED_API:
885-
build_prefix += f'Py_LIMITED_API={Py_LIMITED_API}-'
879+
log(f'{g_py_limited_api=}')
880+
if g_py_limited_api:
881+
build_prefix += f'Py_LIMITED_API={pipcl.current_py_limited_api()}-'
886882
unix_build_dir = f'{mupdf_local}/build/{build_prefix}{build_type}'
887883
# We need MuPDF's Python bindings, so we build MuPDF with
888884
# `mupdf/scripts/mupdfwrap.py` instead of running `make`.
@@ -937,15 +933,15 @@ def _fs_update(text, path):
937933
f.write( text)
938934

939935

940-
def _build_extension( mupdf_local, mupdf_build_dir, build_type, Py_LIMITED_API):
936+
def _build_extension( mupdf_local, mupdf_build_dir, build_type, g_py_limited_api):
941937
'''
942938
Builds Python extension module `_extra`.
943939
944940
Returns leafname of the generated shared libraries within mupdf_build_dir.
945941
'''
946942
(compiler_extra, linker_extra, includes, defines, optimise, debug, libpaths, libs, libraries) \
947-
= _extension_flags( mupdf_local, mupdf_build_dir, build_type, Py_LIMITED_API)
948-
log(f'_build_extension(): {Py_LIMITED_API=} {defines=}')
943+
= _extension_flags( mupdf_local, mupdf_build_dir, build_type, g_py_limited_api)
944+
log(f'_build_extension(): {g_py_limited_api=} {defines=}')
949945
if mupdf_local:
950946
includes = (
951947
f'{mupdf_local}/platform/c++/include',
@@ -988,13 +984,13 @@ def _build_extension( mupdf_local, mupdf_build_dir, build_type, Py_LIMITED_API):
988984
prerequisites_swig = None,
989985
prerequisites_compile = f'{mupdf_local}/include',
990986
prerequisites_link = libraries,
991-
use_so_versioning=not Py_LIMITED_API,
987+
py_limited_api = g_py_limited_api,
992988
)
993989

994990
return path_so_leaf
995991

996992

997-
def _extension_flags( mupdf_local, mupdf_build_dir, build_type, Py_LIMITED_API):
993+
def _extension_flags( mupdf_local, mupdf_build_dir, build_type, g_py_limited_api):
998994
'''
999995
Returns various flags to pass to pipcl.build_extension().
1000996
'''
@@ -1010,9 +1006,9 @@ def _extension_flags( mupdf_local, mupdf_build_dir, build_type, Py_LIMITED_API):
10101006
debug = 'debug' in mupdf_build_dir_flags
10111007
r_extra = ''
10121008
defines = list()
1013-
log(f'{Py_LIMITED_API=}')
1014-
if Py_LIMITED_API:
1015-
defines.append(f'Py_LIMITED_API={Py_LIMITED_API}')
1009+
log(f'{g_py_limited_api=}')
1010+
if g_py_limited_api:
1011+
defines.append(f'Py_LIMITED_API={g_py_limited_api}')
10161012
if windows:
10171013
defines.append('FZ_DLL_CLIENT')
10181014
wp = pipcl.wdev.WindowsPython()
@@ -1188,9 +1184,6 @@ def get_requires_for_build_wheel(config_settings=None):
11881184
[console_scripts]
11891185
pymupdf = pymupdf.__main__:main
11901186
''')
1191-
if Py_LIMITED_API:
1192-
# Wheel will work on all Python versions.
1193-
tag_python = 'py3'
11941187
elif 'b' in PYMUPDF_SETUP_FLAVOUR:
11951188
version = version_b
11961189
name = 'PyMuPDFb'
@@ -1231,6 +1224,7 @@ def get_requires_for_build_wheel(config_settings=None):
12311224
fn_sdist=sdist,
12321225

12331226
tag_python=tag_python,
1227+
py_limited_api=g_py_limited_api,
12341228

12351229
# 30MB: 9 ZIP_DEFLATED
12361230
# 28MB: 9 ZIP_BZIP2

0 commit comments

Comments
 (0)