Skip to content

Commit cb4cb10

Browse files
committed
WIP2
1 parent 83cb4af commit cb4cb10

File tree

14 files changed

+444
-16800
lines changed

14 files changed

+444
-16800
lines changed

.github/workflows/release-wheels.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ jobs:
150150
- name: Install cibuildwheel
151151
run: |
152152
python -m pip install -U pip
153-
python -m pip install cibuildwheel>=2.16
153+
python -m pip install cibuildwheel>=2.21
154154
155155
- name: Build wheels (non-MacOS arm64)
156156
env:
@@ -206,7 +206,7 @@ jobs:
206206
python-version: '3.9'
207207

208208
- name: Install cibuildwheel
209-
run: python -m pip install cibuildwheel==2.16.2 wheel==0.42
209+
run: python -m pip install cibuildwheel>=2.21 wheel>=0.42
210210

211211
- name: Build wheels
212212
env:

build.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
2+
import os
3+
from pathlib import Path
4+
import shutil
5+
from struct import unpack
6+
import subprocess
7+
from typing import List, Any
8+
9+
10+
PACKAGE_DIR = Path(__file__).parent / "openjpeg"
11+
LIB_DIR = Path(__file__).parent / "lib"
12+
BUILD_TOOLS = Path(__file__).parent / "build_tools"
13+
OPENJPEG_SRC = LIB_DIR / "openjpeg" / "src" / "lib" / "openjp2"
14+
INTERFACE_SRC = LIB_DIR / "interface"
15+
BUILD_DIR = LIB_DIR / "openjpeg" / "build"
16+
BACKUP_DIR = BUILD_TOOLS / "backup"
17+
18+
19+
def build(setup_kwargs: Any) -> Any:
20+
from setuptools import Extension
21+
from setuptools.dist import Distribution
22+
import Cython.Compiler.Options
23+
from Cython.Build import build_ext, cythonize
24+
import numpy
25+
26+
setup_oj()
27+
28+
# Determine if system is big endian or not
29+
macros = [
30+
("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION"),
31+
# ("USE_JPIP", "0"),
32+
]
33+
if unpack("h", b"\x00\x01")[0] == 1:
34+
# macros.append(("ON_BE_SYSTEM", None))
35+
macros.append(("OPJ_BIG_ENDIAN", None))
36+
# macros.append(("__BIG_ENDIAN__", None))
37+
38+
ext = Extension(
39+
"_openjpeg",
40+
[os.fspath(p) for p in get_source_files()],
41+
language="c",
42+
include_dirs=[
43+
os.fspath(OPENJPEG_SRC),
44+
os.fspath(INTERFACE_SRC),
45+
numpy.get_include(),
46+
],
47+
extra_compile_args=[],
48+
extra_link_args=[],
49+
define_macros=macros,
50+
)
51+
52+
ext_modules = cythonize(
53+
[ext],
54+
include_path=ext.include_dirs,
55+
language_level=3,
56+
)
57+
58+
dist = Distribution({"ext_modules": ext_modules})
59+
cmd = build_ext(dist)
60+
cmd.ensure_finalized()
61+
cmd.run()
62+
63+
for output in cmd.get_outputs():
64+
output = Path(output)
65+
relative_ext = output.relative_to(cmd.build_lib)
66+
shutil.copyfile(output, relative_ext)
67+
68+
reset_oj()
69+
70+
return setup_kwargs
71+
72+
73+
def get_source_files() -> List[Path]:
74+
"""Return a list of paths to the source files to be compiled."""
75+
source_files = [
76+
INTERFACE_SRC / "decode.c",
77+
INTERFACE_SRC / "encode.c",
78+
INTERFACE_SRC / "color.c",
79+
INTERFACE_SRC / "utils.c",
80+
]
81+
for fname in OPENJPEG_SRC.glob("*"):
82+
if fname.parts[-1].startswith("test"):
83+
continue
84+
85+
if fname.parts[-1].startswith("bench"):
86+
continue
87+
88+
if fname.suffix == ".c":
89+
source_files.append(fname)
90+
91+
source_files = [p.relative_to(Path(__file__).parent) for p in source_files]
92+
source_files.insert(0, PACKAGE_DIR / "_openjpeg.pyx")
93+
94+
return source_files
95+
96+
97+
def setup_oj() -> None:
98+
"""Run custom cmake."""
99+
base_dir = LIB_DIR / "openjpeg"
100+
p_openjpeg = base_dir / "src" / "lib" / "openjp2" / "openjpeg.c"
101+
102+
# Backup original CMakeLists.txt and openjpeg.c files
103+
if os.path.exists(BACKUP_DIR):
104+
shutil.rmtree(BACKUP_DIR)
105+
106+
BACKUP_DIR.mkdir(exist_ok=True, parents=True)
107+
108+
shutil.copy(
109+
LIB_DIR / "openjpeg" / "CMakeLists.txt",
110+
BACKUP_DIR / "CMakeLists.txt.backup",
111+
)
112+
shutil.copy(
113+
OPENJPEG_SRC / "openjpeg.c",
114+
BACKUP_DIR / "openjpeg.c.backup",
115+
)
116+
117+
# Copy custom CMakeLists.txt file to openjpeg base dir
118+
shutil.copy(
119+
BUILD_TOOLS / "cmake" / "CMakeLists.txt",
120+
LIB_DIR / "openjpeg" / "CMakeLists.txt",
121+
)
122+
# Edit openjpeg.c to remove the OPJ_API declaration
123+
with p_openjpeg.open("r") as f:
124+
data = f.readlines()
125+
126+
data = [
127+
line.replace("OPJ_API ", "")
128+
if line.startswith("OPJ_API ") else line for line in data
129+
]
130+
with p_openjpeg.open("w") as f:
131+
f.write("".join(data))
132+
133+
if os.path.exists(BUILD_DIR):
134+
shutil.rmtree(BUILD_DIR)
135+
136+
try:
137+
os.remove(INTERFACE_SRC / "opj_config.h")
138+
os.remove(INTERFACE_SRC / "opj_config_private.h")
139+
except:
140+
pass
141+
142+
os.mkdir(BUILD_DIR)
143+
cur_dir = os.getcwd()
144+
os.chdir(BUILD_DIR)
145+
subprocess.call(['cmake', os.fspath((LIB_DIR / "openjpeg").resolve(strict=True))])
146+
os.chdir(cur_dir)
147+
148+
# Turn off JPIP
149+
if os.path.exists(INTERFACE_SRC / "opj_config.h"):
150+
with open(INTERFACE_SRC / "opj_config.h", "a") as f:
151+
f.write("\n")
152+
f.write("#define USE_JPIP 0")
153+
154+
# Use our own OPJ_BIG_ENDIAN macro
155+
if os.path.exists(INTERFACE_SRC / "opj_config_private.h"):
156+
with open(INTERFACE_SRC / "opj_config_private.h", "r") as f:
157+
lines = f.readlines()
158+
159+
with open(INTERFACE_SRC / "opj_config_private.h", "w") as f:
160+
f.writelines(lines[:-5])
161+
162+
163+
def reset_oj() -> None:
164+
# Restore submodule to original state
165+
# Restore CMakeLists.txt and openjpeg.c files
166+
if (BACKUP_DIR / "CMakeLists.txt.backup").exists():
167+
shutil.copy(
168+
BACKUP_DIR / "CMakeLists.txt.backup",
169+
LIB_DIR / "openjpeg" / "CMakeLists.txt",
170+
)
171+
172+
if (BACKUP_DIR / "openjpeg.c.backup").exists():
173+
shutil.copy(
174+
BACKUP_DIR / "openjpeg.c.backup",
175+
OPENJPEG_SRC / "openjpeg.c",
176+
)
177+
178+
# Cleanup added directories
179+
if os.path.exists(BUILD_DIR):
180+
shutil.rmtree(BUILD_DIR)
181+
182+
if os.path.exists(BACKUP_DIR):
183+
shutil.rmtree(BACKUP_DIR)

0 commit comments

Comments
 (0)