forked from randovania/randovania
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.py
More file actions
175 lines (144 loc) · 5.24 KB
/
setup.py
File metadata and controls
175 lines (144 loc) · 5.24 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
from __future__ import annotations
import os
import shutil
import sys
from pathlib import Path
from Cython.Build import cythonize
from setuptools import Command, Extension, setup
from setuptools.command.build import build
parent = Path(__file__).parent
# Check if enable-cython file exists and read its content
enable_cython_file = parent.joinpath("randovania", "enable-cython")
if enable_cython_file.is_file():
enable_cython_content = enable_cython_file.read_text().strip()
else:
enable_cython_content = ""
should_compile_env = os.getenv("RANDOVANIA_COMPILE")
if should_compile_env is None:
should_compile = enable_cython_file.is_file()
else:
should_compile = should_compile_env != "0"
# Enable coverage tracing only if enable-cython contains "linetrace"
enable_coverage_tracing = "linetrace" in enable_cython_content
if enable_coverage_tracing:
print("Cython coverage tracing enabled")
class CopyReadmeCommand(Command):
"""Custom build command."""
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
shutil.copy2(parent.joinpath("README.md"), parent.joinpath("randovania", "data", "README.md"))
class DeleteUnknownNativeCommand(Command):
"""Custom build command."""
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
root = parent.joinpath("randovania")
cython_files: list[Path] = []
for path, dirnames, filenames in root.walk():
relative = path.relative_to(parent)
if len(relative.parts) < 2 or relative.parts[1] != "data":
for file in filenames:
if file.endswith((".pyd", ".cpp", ".so")):
cython_files.append(relative.joinpath(file))
for file in cython_files:
associated_py_file = file.as_posix().split(".", 1)[0] + ".py"
if not should_compile or associated_py_file not in cythonize_files:
print("Deleting", file)
file.unlink()
class CustomBuild(build):
sub_commands = [
("copy_readme", None),
("delete_unknown_native", None),
*build.sub_commands,
]
cythonize_files = [
"randovania/lib/bitmask.py",
"randovania/game_description/resources/resource_collection.py",
"randovania/graph/graph_requirement.py",
"randovania/graph/world_graph.py",
"randovania/graph/state_native.py",
"randovania/resolver/resolver_native.py",
"randovania/generator/generator_native.py",
]
ext_modules = None
if should_compile:
debug_mode = os.getenv("RANDOVANIA_DEBUG", "0") != "0"
profiling_mode = os.getenv("RANDOVANIA_PROFILE", "0") != "0"
if sys.platform == "win32":
# MSVC
extra_compile_args = [
"/std:c++20",
"/Zi", # Generate debug info (PDB)
# Cython boilerplate triggers warning "function call missing argument list", unrelated to our code
"/wd4551",
]
extra_link_args = []
if profiling_mode:
# Add profiling flags for MSVC
extra_compile_args.extend(
[
"/O2", # Optimize for speed (but keep symbols)
"/Oy-", # Disable frame pointer omission
]
)
extra_link_args.extend(
[
"/DEBUG", # Generate PDB file
"/PROFILE", # Enable profiling
]
)
elif debug_mode:
extra_compile_args.extend(["/Od"]) # Disable optimizations
else:
# GCC/Clang
extra_compile_args = [
"-std=c++20",
"-g", # Debug symbols
]
extra_link_args = ["-g"]
if profiling_mode:
# Add profiling flags for GCC/Clang
extra_compile_args.extend(
[
"-O2", # Optimize but keep symbols
"-fno-omit-frame-pointer", # Keep frame pointers
"-fno-inline-functions", # Don't inline (for clearer profiling)
]
)
elif debug_mode:
extra_compile_args.extend(["-O0", "-fno-omit-frame-pointer"]) # no optimization
# Conditionally add coverage tracing macros
define_macros = [("CYTHON_TRACE", "1"), ("CYTHON_TRACE_NOGIL", "1")] if enable_coverage_tracing else []
ext_modules = cythonize(
[
Extension(
file.replace("/", ".")[:-3],
sources=[file],
language="c++",
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
define_macros=define_macros,
)
for file in cythonize_files
],
annotate=True,
compiler_directives={
"linetrace": enable_coverage_tracing, # Enable line tracing only when needed for coverage
"profile": profiling_mode, # Enable profiling hooks
},
gdb_debug=debug_mode, # Add Cython debugging support
emit_linenums=True,
)
setup(
ext_modules=ext_modules,
cmdclass={
"copy_readme": CopyReadmeCommand,
"delete_unknown_native": DeleteUnknownNativeCommand,
"build": CustomBuild,
},
)