Mercurial > hgrepos > Python2 > PyMuPDF
comparison setup.py @ 41:71bcc18e306f
MERGE: New upstream PyMuPDF v1.26.5 including MuPDF v1.26.10
BUGS: Needs some additional changes yet.
Not yet tested.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 11 Oct 2025 15:24:40 +0200 |
| parents | 14b91574d44a a6bc019ac0b2 |
| children | 0a8b06e38e19 |
comparison
equal
deleted
inserted
replaced
| 38:8934ac156ef5 | 41:71bcc18e306f |
|---|---|
| 86 If unset or '-', use internal hard-coded default MuPDF location. | 86 If unset or '-', use internal hard-coded default MuPDF location. |
| 87 Otherwise overrides location of MuPDF when building PyMuPDF: | 87 Otherwise overrides location of MuPDF when building PyMuPDF: |
| 88 Empty string: | 88 Empty string: |
| 89 Build PyMuPDF with the system MuPDF. | 89 Build PyMuPDF with the system MuPDF. |
| 90 A string starting with 'git:': | 90 A string starting with 'git:': |
| 91 Use `git clone` to get a MuPDF checkout. We use the | 91 We use `git` commands to clone/update a local MuPDF checkout. |
| 92 string in the git clone command; it must contain the git | 92 Should match `git:[--branch <branch>][--tag <tag>][<remote>]`. |
| 93 URL from which to clone, and can also contain other `git | 93 If <remote> is omitted we use a default. |
| 94 clone` args, for example: | 94 For example: |
| 95 PYMUPDF_SETUP_MUPDF_BUILD="git:--branch master https://github.com/ArtifexSoftware/mupdf.git" | 95 PYMUPDF_SETUP_MUPDF_BUILD="git:--branch master" |
| 96 Passed as <text> arg to pipcl.git_get(). | |
| 96 Otherwise: | 97 Otherwise: |
| 97 Location of mupdf directory. | 98 Location of mupdf directory. |
| 98 | 99 |
| 99 PYMUPDF_SETUP_MUPDF_BSYMBOLIC | 100 PYMUPDF_SETUP_MUPDF_BSYMBOLIC |
| 100 If '0' we do not link libmupdf.so with -Bsymbolic. | 101 If '0' we do not link libmupdf.so with -Bsymbolic. |
| 459 run(f'cd {directory} && git diff') | 460 run(f'cd {directory} && git diff') |
| 460 | 461 |
| 461 | 462 |
| 462 mupdf_tgz = os.path.abspath( f'{__file__}/../mupdf.tgz') | 463 mupdf_tgz = os.path.abspath( f'{__file__}/../mupdf.tgz') |
| 463 | 464 |
| 464 def get_mupdf_internal(out, location=None, sha=None, local_tgz=None): | 465 def get_mupdf_internal(out, location=None, local_tgz=None): |
| 465 ''' | 466 ''' |
| 466 Gets MuPDF as either a .tgz or a local directory. | 467 Gets MuPDF as either a .tgz or a local directory. |
| 467 | 468 |
| 468 Args: | 469 Args: |
| 469 out: | 470 out: |
| 472 location: | 473 location: |
| 473 First, if None we set to hard-coded default URL or git location. | 474 First, if None we set to hard-coded default URL or git location. |
| 474 If starts with 'git:', should be remote git location. | 475 If starts with 'git:', should be remote git location. |
| 475 Otherwise if containing '://' should be URL for .tgz. | 476 Otherwise if containing '://' should be URL for .tgz. |
| 476 Otherwise should path of local mupdf checkout. | 477 Otherwise should path of local mupdf checkout. |
| 477 sha: | |
| 478 If not None and we use git clone, we checkout this sha. | |
| 479 local_tgz: | 478 local_tgz: |
| 480 If not None, must be local .tgz file. | 479 If not None, must be local .tgz file. |
| 481 Returns: | 480 Returns: |
| 482 (path, location): | 481 (path, location): |
| 483 `path` is absolute path of local directory or .tgz containing | 482 `path` is absolute path of local directory or .tgz containing |
| 485 | 484 |
| 486 `location_out` is `location` if not None, else the hard-coded | 485 `location_out` is `location` if not None, else the hard-coded |
| 487 default location. | 486 default location. |
| 488 | 487 |
| 489 ''' | 488 ''' |
| 490 log(f'get_mupdf_internal(): {out=} {location=} {sha=}') | 489 log(f'get_mupdf_internal(): {out=} {location=}') |
| 491 assert out in ('dir', 'tgz') | 490 assert out in ('dir', 'tgz') |
| 492 if location is None: | 491 if location is None: |
| 493 location = f'https://mupdf.com/downloads/archive/mupdf-{version_mupdf}-source.tar.gz' | 492 location = f'https://mupdf.com/downloads/archive/mupdf-{version_mupdf}-source.tar.gz' |
| 494 #location = 'git:--branch master https://github.com/ArtifexSoftware/mupdf.git' | 493 #location = 'git:--branch master https://github.com/ArtifexSoftware/mupdf.git' |
| 495 | 494 |
| 499 | 498 |
| 500 local_dir = None | 499 local_dir = None |
| 501 if local_tgz: | 500 if local_tgz: |
| 502 assert os.path.isfile(local_tgz) | 501 assert os.path.isfile(local_tgz) |
| 503 elif location.startswith( 'git:'): | 502 elif location.startswith( 'git:'): |
| 504 location_git = location[4:] | |
| 505 local_dir = 'mupdf-git' | 503 local_dir = 'mupdf-git' |
| 506 | 504 pipcl.git_get(local_dir, text=location, remote='https://github.com/ArtifexSoftware/mupdf.git') |
| 507 # Try to update existing checkout. | 505 |
| 508 e = run(f'cd {local_dir} && git pull && git submodule update --init', check=False) | |
| 509 if e: | |
| 510 # No existing git checkout, so do a fresh clone. | |
| 511 _fs_remove(local_dir) | |
| 512 gitargs = location[4:] | |
| 513 run(f'git clone --recursive --depth 1 --shallow-submodules {gitargs} {local_dir}') | |
| 514 | |
| 515 # Show sha of checkout. | 506 # Show sha of checkout. |
| 516 run( f'cd {local_dir} && git show --pretty=oneline|head -n 1', check=False) | 507 run( |
| 517 if sha: | 508 f'cd {local_dir} && git show --pretty=oneline|head -n 1', |
| 518 run( f'cd {local_dir} && git checkout {sha}') | 509 check = False, |
| 510 prefix = 'mupdf git id: ', | |
| 511 ) | |
| 519 elif '://' in location: | 512 elif '://' in location: |
| 520 # Download .tgz. | 513 # Download .tgz. |
| 521 local_tgz = os.path.basename( location) | 514 local_tgz = os.path.basename( location) |
| 522 suffix = '.tar.gz' | 515 suffix = '.tar.gz' |
| 523 assert location.endswith(suffix), f'Unrecognised suffix in remote URL {location=}.' | 516 assert location.endswith(suffix), f'Unrecognised suffix in remote URL {location=}.' |
| 608 freebsd = sys.platform.startswith( 'freebsd') | 601 freebsd = sys.platform.startswith( 'freebsd') |
| 609 darwin = sys.platform.startswith( 'darwin') | 602 darwin = sys.platform.startswith( 'darwin') |
| 610 windows = platform.system() == 'Windows' or platform.system().startswith('CYGWIN') | 603 windows = platform.system() == 'Windows' or platform.system().startswith('CYGWIN') |
| 611 msys2 = platform.system().startswith('MSYS_NT-') | 604 msys2 = platform.system().startswith('MSYS_NT-') |
| 612 | 605 |
| 613 pyodide_flags = '-fwasm-exceptions' | |
| 614 | |
| 615 if os.environ.get('PYODIDE') == '1': | 606 if os.environ.get('PYODIDE') == '1': |
| 616 if os.environ.get('OS') != 'pyodide': | 607 if os.environ.get('OS') != 'pyodide': |
| 617 log('PYODIDE=1, setting OS=pyodide.') | 608 log('PYODIDE=1, setting OS=pyodide.') |
| 618 os.environ['OS'] = 'pyodide' | 609 os.environ['OS'] = 'pyodide' |
| 619 os.environ['XCFLAGS'] = pyodide_flags | |
| 620 os.environ['XCXXFLAGS'] = pyodide_flags | |
| 621 | 610 |
| 622 pyodide = os.environ.get('OS') == 'pyodide' | 611 pyodide = os.environ.get('OS') == 'pyodide' |
| 623 | 612 |
| 624 def build(): | 613 def build(): |
| 625 ''' | 614 ''' |
| 738 add('b', f'{mupdf_build_dir}/libmupdfcpp.so', to_dir) | 727 add('b', f'{mupdf_build_dir}/libmupdfcpp.so', to_dir) |
| 739 add('b', f'{mupdf_build_dir}/libmupdf.dylib', to_dir) | 728 add('b', f'{mupdf_build_dir}/libmupdf.dylib', to_dir) |
| 740 add('d', f'{mupdf_build_dir}/libmupdf-threads.a', f'{to_dir_d}/lib/') | 729 add('d', f'{mupdf_build_dir}/libmupdf-threads.a', f'{to_dir_d}/lib/') |
| 741 elif pyodide: | 730 elif pyodide: |
| 742 add('p', f'{mupdf_build_dir}/_mupdf.so', to_dir) | 731 add('p', f'{mupdf_build_dir}/_mupdf.so', to_dir) |
| 743 add('b', f'{mupdf_build_dir}/libmupdfcpp.so', 'PyMuPDF.libs/') | 732 add('b', f'{mupdf_build_dir}/libmupdfcpp.so', to_dir) |
| 744 add('b', f'{mupdf_build_dir}/libmupdf.so', 'PyMuPDF.libs/') | 733 add('b', f'{mupdf_build_dir}/libmupdf.so', to_dir) |
| 745 else: | 734 else: |
| 746 add('p', f'{mupdf_build_dir}/_mupdf.so', to_dir) | 735 add('p', f'{mupdf_build_dir}/_mupdf.so', to_dir) |
| 747 add('b', pipcl.get_soname(f'{mupdf_build_dir}/libmupdfcpp.so'), to_dir) | 736 add('b', pipcl.get_soname(f'{mupdf_build_dir}/libmupdfcpp.so'), to_dir) |
| 748 add('b', pipcl.get_soname(f'{mupdf_build_dir}/libmupdf.so'), to_dir) | 737 add('b', pipcl.get_soname(f'{mupdf_build_dir}/libmupdf.so'), to_dir) |
| 749 add('d', f'{mupdf_build_dir}/libmupdf-threads.a', f'{to_dir_d}/lib/') | 738 add('d', f'{mupdf_build_dir}/libmupdf-threads.a', f'{to_dir_d}/lib/') |
| 782 try: | 771 try: |
| 783 return int(text) | 772 return int(text) |
| 784 except Exception: | 773 except Exception: |
| 785 return 0 | 774 return 0 |
| 786 swig_version_tuple = tuple(int_or_0(i) for i in swig_version.split('.')) | 775 swig_version_tuple = tuple(int_or_0(i) for i in swig_version.split('.')) |
| 776 version_p_tuple = tuple(int_or_0(i) for i in version_p.split('.')) | |
| 787 log(f'{swig_version=}') | 777 log(f'{swig_version=}') |
| 788 text = '' | 778 text = '' |
| 789 if os.path.isdir(mupdf_location): | 779 if os.path.isdir(mupdf_location): |
| 790 mupdf_location = mupdf_location.rstrip('/') | 780 mupdf_location = mupdf_location.rstrip('/') |
| 791 text += 'mupdf_location = ' + repr(os.path.basename(mupdf_location)) + '\n' | 781 text += 'mupdf_location = ' + repr(os.path.basename(mupdf_location)) + '\n' |
| 792 else: | 782 else: |
| 793 text += f'mupdf_location = {mupdf_location!r}\n' | 783 text += f'mupdf_location = {mupdf_location!r}\n' |
| 794 text += f'pymupdf_version = {version_p!r}\n' | 784 text += f'pymupdf_version = {version_p!r}\n' |
| 785 text += f'pymupdf_version_tuple = {version_p_tuple!r}\n' | |
| 795 text += f'pymupdf_git_sha = {sha!r}\n' | 786 text += f'pymupdf_git_sha = {sha!r}\n' |
| 796 text += f'pymupdf_git_diff = {diff!r}\n' | 787 text += f'pymupdf_git_diff = {diff!r}\n' |
| 797 text += f'pymupdf_git_branch = {branch!r}\n' | 788 text += f'pymupdf_git_branch = {branch!r}\n' |
| 798 text += f'swig_version = {swig_version!r}\n' | 789 text += f'swig_version = {swig_version!r}\n' |
| 799 text += f'swig_version_tuple = {swig_version_tuple!r}\n' | 790 text += f'swig_version_tuple = {swig_version_tuple!r}\n' |
| 1256 compiler_extra += f' {cflags}' | 1247 compiler_extra += f' {cflags}' |
| 1257 cxxflags = os.environ.get('CXXFLAGS') | 1248 cxxflags = os.environ.get('CXXFLAGS') |
| 1258 if cxxflags: | 1249 if cxxflags: |
| 1259 compiler_extra += f' {cxxflags}' | 1250 compiler_extra += f' {cxxflags}' |
| 1260 | 1251 |
| 1261 if pyodide: | |
| 1262 compiler_extra += f' {pyodide_flags}' | |
| 1263 linker_extra += f' {pyodide_flags}' | |
| 1264 | 1252 |
| 1265 if not darwin and (platform.system() != 'Windows'): | 1253 if not darwin and (platform.system() != 'Windows'): |
| 1266 # *BSD and Linux | 1254 # *BSD and Linux |
| 1267 # Full RELRO | 1255 # Full RELRO |
| 1268 linker_extra += ' -Wl,-z,relro,-z,now' | 1256 linker_extra += ' -Wl,-z,relro,-z,now' |
| 1333 | 1321 |
| 1334 # We generate different wheels depending on PYMUPDF_SETUP_FLAVOUR. | 1322 # We generate different wheels depending on PYMUPDF_SETUP_FLAVOUR. |
| 1335 # | 1323 # |
| 1336 | 1324 |
| 1337 # PyMuPDF version. | 1325 # PyMuPDF version. |
| 1338 version_p = '1.26.4+2' | 1326 version_p = '1.26.5+XXXFIXME0' |
| 1339 | 1327 |
| 1340 version_mupdf = '1.26.7' | 1328 version_mupdf = '1.26.10' |
| 1341 | 1329 |
| 1342 # PyMuPDFb version. This is the PyMuPDF version whose PyMuPDFb wheels we will | 1330 # PyMuPDFb version. This is the PyMuPDF version whose PyMuPDFb wheels we will |
| 1343 # (re)use if generating separate PyMuPDFb wheels. Though as of PyMuPDF-1.24.11 | 1331 # (re)use if generating separate PyMuPDFb wheels. Though as of PyMuPDF-1.24.11 |
| 1344 # (2024-10-03) we no longer use PyMuPDFb wheels so this is actually unused. | 1332 # (2024-10-03) we no longer use PyMuPDFb wheels so this is actually unused. |
| 1345 # | 1333 # |
| 1472 if libclang: | 1460 if libclang: |
| 1473 print(f'Overriding to use {libclang=}.') | 1461 print(f'Overriding to use {libclang=}.') |
| 1474 ret.append(libclang) | 1462 ret.append(libclang) |
| 1475 elif openbsd: | 1463 elif openbsd: |
| 1476 print(f'OpenBSD: libclang not available via pip; assuming `pkg_add py3-llvm`.') | 1464 print(f'OpenBSD: libclang not available via pip; assuming `pkg_add py3-llvm`.') |
| 1477 elif darwin and platform.machine() == 'arm64': | |
| 1478 print(f'MacOS/arm64: forcing use of libclang 16.0.6 because 18.1.1 known to fail with `clang.cindex.TranslationUnitLoadError: Error parsing translation unit.`') | |
| 1479 ret.append('libclang==16.0.6') | |
| 1480 elif darwin and platform_release_tuple() < (18,): | 1465 elif darwin and platform_release_tuple() < (18,): |
| 1481 # There are still of problems when building on old macos. | 1466 # There are still of problems when building on old macos. |
| 1482 ret.append('libclang==14.0.6') | 1467 ret.append('libclang==14.0.6') |
| 1483 else: | 1468 else: |
| 1484 ret.append('libclang') | 1469 ret.append('libclang') |
