-
Notifications
You must be signed in to change notification settings - Fork 1
/
hatch_build.py
174 lines (141 loc) · 5.44 KB
/
hatch_build.py
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
import multiprocessing
import os
import platform
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 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(".", "_")
@cached_property
def cmake_build_dir(self):
p = Path(self.directory) / "cmake_build"
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):
args = list(map(str, args))
with group("Running", *args):
return subprocess.run(args, capture_output=False, check=True, cwd=self.cmake_build_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(build_data)
pprint(self.build_config.__dict__)
# disable march=native optimizations (including SSE3)
if is_cibuildwheel():
comp_spec_cmake = self.ogdf_src_dir / "cmake" / "compiler-specifics.cmake"
with open(comp_spec_cmake, "rt") as f:
lines = f.readlines()
with open(comp_spec_cmake, "wt") as f:
f.writelines("# " + l if "march=native" in l and not l.strip().startswith("#") else l for l in lines)
CONFIG = "Debug"
flags = [
"-DCMAKE_BUILD_TYPE=" + CONFIG, "-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",
]
if CONFIG == "Debug" and not is_windows():
flags.extend([
"-DOGDF_USE_ASSERT_EXCEPTIONS=ON", # "-DOGDF_USE_ASSERT_EXCEPTIONS_WITH=ON_LIBUNWIND",
])
flags.extend([
"-DOGDF_MEMORY_MANAGER=POOL_TS",
# "-DOGDF_MEMORY_MANAGER=MALLOC_TS", "-DOGDF_LEAK_CHECK=ON",
])
self.run("cmake", self.ogdf_src_dir, *flags)
# import IPython
# IPython.embed()
# windows needs config repeated but no parallel
build_opts = []
if not is_windows():
build_opts = ["--parallel", str(multiprocessing.cpu_count())]
self.run("cmake", "--build", ".", "--config", CONFIG, *build_opts)
self.run("cmake", "--install", ".", "--config", CONFIG)
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)
shutil.rmtree(self.cmake_install_dir)