-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhatch_build.py
More file actions
189 lines (154 loc) · 6.25 KB
/
hatch_build.py
File metadata and controls
189 lines (154 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import multiprocessing
import os
import platform
import re
import subprocess
import sys
import sysconfig
from contextlib import contextmanager
from pathlib import Path
from pprint import pprint
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
try:
from functools import cached_property
except:
cached_property = property
def is_github_actions():
return os.getenv("GITHUB_ACTIONS", None) == "true"
def is_cibuildwheel():
return os.environ.get("CIBUILDWHEEL", "0") == "1"
def is_windows():
return platform.system() == "Windows"
def is_macos():
return platform.system() == "Darwin"
def sync():
sys.stdout.flush()
sys.stderr.flush()
if hasattr(os, "sync"):
os.sync()
@contextmanager
def group(*names):
if is_github_actions():
print("::group::%s" % " ".join(map(str, names)))
else:
print()
print(*names)
sync()
yield
sync()
if is_github_actions():
print("::endgroup::")
else:
print()
class CustomBuildHook(BuildHookInterface):
@cached_property
def tag(self):
plat = os.getenv("AUDITWHEEL_PLAT", None)
if not plat:
plat = sysconfig.get_platform()
return "py3-none-%s" % plat.replace("-", "_").replace(".", "_")
def cmake_build_dir(self, config):
p = Path(self.directory) / f"cmake_build_{config}"
p.mkdir(parents=True, exist_ok=True)
return p
@cached_property
def cmake_install_dir(self):
if is_windows():
p = Path(self.root) / "src" / "ogdf_wheel" / "install"
else:
p = Path(self.root) / "install"
p.mkdir(parents=True, exist_ok=True)
return p
@cached_property
def ogdf_src_dir(self):
return Path(self.root) / "ogdf"
def run(self, *args, dir):
args = list(map(str, args))
with group("Running", *args):
return subprocess.run(args, capture_output=False, check=True, cwd=dir)
def dump_files(self, dir):
with group("Index of", dir):
for dirpath, dirnames, filenames in os.walk(dir):
for file in filenames:
print(dirpath + "/" + file)
if not dirnames and not filenames:
print(dirpath, "(empty)")
def initialize(self, version, build_data):
"""
This occurs immediately before each build.
Any modifications to the build data will be seen by the build target.
"""
if is_cibuildwheel() and is_github_actions():
print("::endgroup::") # close the group from cibuildwheel
build_data["pure_python"] = False
build_data["tag"] = self.tag
print("Set wheel tag to", build_data["tag"])
if is_windows():
del self.build_config.target_config["shared-data"]
with group("Config"):
pprint({
"root": self.root,
"directory": self.directory,
"ogdf_src_dir": self.ogdf_src_dir,
"cmake_install_dir": self.cmake_install_dir,
"cmake_build_dir debug": self.cmake_build_dir("debug"),
"cmake_build_dir release": self.cmake_build_dir("release"),
})
pprint(build_data)
pprint(self.build_config.__dict__)
# remove version information from .so name
cmake_file = self.ogdf_src_dir / "CMakeLists.txt"
with open(cmake_file, "rt") as f:
lines = f.readlines()
with open(cmake_file, "wt") as f:
f.writelines(re.sub(' *VERSION "20[0-9.]+"', '', l) for l in lines)
flags = [
"-DBUILD_SHARED_LIBS=ON",
"-DCMAKE_INSTALL_PREFIX=%s" % self.cmake_install_dir,
"-DOGDF_WARNING_ERRORS=OFF",
"-DCMAKE_BUILD_RPATH=$ORIGIN;@loader_path", "-DCMAKE_INSTALL_RPATH=$ORIGIN;@loader_path",
"-DMACOSX_RPATH=TRUE",
"-DCMAKE_INSTALL_LIBDIR=lib", # instead of lib64 https://stackoverflow.com/a/76528304
]
if is_windows():
flags.append("-DOGDF_MEMORY_MANAGER=MALLOC_TS")
else:
flags.append("-DOGDF_MEMORY_MANAGER=POOL_TS")
release_dir = self.cmake_build_dir("release")
self.run("cmake", self.ogdf_src_dir, "-DCMAKE_BUILD_TYPE=Release", *flags, dir=release_dir)
self.run("cmake", "--build", ".", "--config", "Release", "--parallel", str(multiprocessing.cpu_count()),
dir=release_dir)
self.run("cmake", "--install", ".", "--config", "Release", dir=release_dir)
if not is_windows():
flags.extend([
"-DOGDF_USE_ASSERT_EXCEPTIONS=ON", # "-DOGDF_USE_ASSERT_EXCEPTIONS_WITH=ON_LIBUNWIND",
])
debug_dir = self.cmake_build_dir("debug")
self.run("cmake", self.ogdf_src_dir, "-DCMAKE_BUILD_TYPE=Debug", *flags, dir=debug_dir)
self.run("cmake", "--build", ".", "--config", "Debug", "--parallel", str(multiprocessing.cpu_count()),
dir=debug_dir)
self.run("cmake", "--install", ".", "--config", "Debug", dir=debug_dir)
# import IPython
# IPython.embed()
self.dump_files(self.directory)
self.dump_files(self.root)
def finalize(self, version, build_data, artifact_path):
"""
This occurs immediately after each build and will not run if the `--hooks-only` flag
was passed to the [`build`](../cli/reference.md#hatch-build) command.
The build data will reflect any modifications done by the target during the build.
"""
with group("Wheel files RECORD"):
from zipfile import ZipFile
with ZipFile(artifact_path) as zip:
print(zip.read(self.build_config.builder.project_id + ".dist-info/RECORD").decode("ascii"))
def clean(self, versions):
"""
This occurs before the build process if the `-c`/`--clean` flag was passed to
the [`build`](../cli/reference.md#hatch-build) command, or when invoking
the [`clean`](../cli/reference.md#hatch-clean) command.
"""
import shutil
shutil.rmtree(self.cmake_build_dir("release"), ignore_errors=True)
shutil.rmtree(self.cmake_build_dir("debug"), ignore_errors=True)
shutil.rmtree(self.cmake_install_dir, ignore_errors=True)