|
| 1 | +from pathlib import Path |
1 | 2 | from setuptools import setup, Extension
|
2 | 3 | import subprocess
|
| 4 | +import json |
3 | 5 | import shlex
|
4 |
| -import glob |
5 | 6 | import sys
|
6 | 7 | import os
|
7 | 8 |
|
8 | 9 |
|
9 |
| -compiler_options = {"unix": ["-mavx2"], "msvc": ["/arch:AVX2"]} |
10 |
| - |
11 |
| -compiler_type = "msvc" if os.name == "nt" else "unix" |
| 10 | +extra_compiler_options = [] |
12 | 11 |
|
| 12 | +if sys.platform == "linux" or sys.platform == "linux2": |
| 13 | + extra_compiler_options.append("-mavx2") |
| 14 | +elif sys.platform == "win32": |
| 15 | + extra_compiler_options.append("/arch:AVX2") |
| 16 | +elif sys.platform == "darwin": |
| 17 | + pass |
13 | 18 |
|
14 | 19 | extensions = [
|
15 | 20 | Extension(
|
16 | 21 | "geometry",
|
17 | 22 | sources=["src_c/geometry.c"],
|
18 |
| - extra_compile_args=compiler_options[compiler_type], |
| 23 | + extra_compile_args=extra_compiler_options, |
19 | 24 | )
|
20 | 25 | ]
|
21 | 26 |
|
22 | 27 |
|
| 28 | +def consume_arg(arg: str) -> bool: |
| 29 | + if arg in sys.argv: |
| 30 | + sys.argv.remove(arg) |
| 31 | + return True |
| 32 | + return False |
| 33 | + |
| 34 | + |
| 35 | +def get_geometry_cache_dir() -> Path: |
| 36 | + path = Path("./__geometry_cache__") |
| 37 | + |
| 38 | + path.mkdir(exist_ok=True) |
| 39 | + |
| 40 | + return path |
| 41 | + |
| 42 | + |
| 43 | +def get_times_json_file() -> Path: |
| 44 | + path = get_geometry_cache_dir() / "times.json" |
| 45 | + |
| 46 | + path.touch(exist_ok=True) |
| 47 | + |
| 48 | + return path |
| 49 | + |
| 50 | + |
| 51 | +def update_times_file() -> None: |
| 52 | + files = list(Path("./src_c/").glob("**/*.[c|h]")) |
| 53 | + |
| 54 | + data: Dict[str, float] = {str(file): os.path.getmtime(str(file)) for file in files} |
| 55 | + |
| 56 | + with open(get_times_json_file(), "w") as f: |
| 57 | + f.truncate(0) |
| 58 | + f.write(json.dumps(data, indent=4)) |
| 59 | + |
| 60 | + |
| 61 | +def needs_to_be_rebuild() -> bool: |
| 62 | + files = list(Path("./src_c/").glob("**/*.[c|h]")) |
| 63 | + |
| 64 | + with open(get_times_json_file(), "r+") as f: |
| 65 | + file_contents = f.read() |
| 66 | + data: Dict[str, float] |
| 67 | + |
| 68 | + if file_contents == "": |
| 69 | + data = {} |
| 70 | + else: |
| 71 | + data = json.loads(file_contents) |
| 72 | + |
| 73 | + if not data: |
| 74 | + for file in files: |
| 75 | + data[str(file)] = os.path.getmtime(str(file)) |
| 76 | + |
| 77 | + f.write(json.dumps(data, indent=4)) |
| 78 | + |
| 79 | + return True |
| 80 | + |
| 81 | + result = False |
| 82 | + |
| 83 | + for file in files: |
| 84 | + if data[str(file)] != os.path.getmtime(str(file)): |
| 85 | + data[str(file)] = os.path.getmtime(str(file)) |
| 86 | + result = True |
| 87 | + |
| 88 | + with open(get_times_json_file(), "w") as f: |
| 89 | + f.truncate(0) |
| 90 | + f.write(json.dumps(data, indent=4)) |
| 91 | + |
| 92 | + return result |
| 93 | + |
| 94 | + |
23 | 95 | def build() -> None:
|
| 96 | + if not needs_to_be_rebuild(): |
| 97 | + print("latest version of geometry already built") |
| 98 | + return |
| 99 | + print("building latest version of geometry...") |
| 100 | + |
| 101 | + with open("src_c/geometry.c", "r+") as f: |
| 102 | + original_geometry_c = f.read() |
| 103 | + f.write(" ") |
| 104 | + |
24 | 105 | setup(
|
25 | 106 | name="geometry",
|
26 | 107 | ext_modules=extensions,
|
27 | 108 | )
|
28 | 109 |
|
| 110 | + with open("src_c/geometry.c", "w") as f: |
| 111 | + f.truncate(0) |
| 112 | + f.write(original_geometry_c) |
| 113 | + |
| 114 | + update_times_file() |
| 115 | + |
29 | 116 |
|
30 | 117 | if __name__ == "__main__":
|
31 |
| - if "format" in sys.argv: |
32 |
| - c_files = glob.glob("src_c/*.c") |
33 |
| - h_files = glob.glob("src_c/include/*.h") |
| 118 | + for arg in sys.argv: |
| 119 | + if arg in ("--format", "install", "--test"): |
| 120 | + break |
| 121 | + else: |
| 122 | + setup( |
| 123 | + name="geometry", |
| 124 | + ext_modules=extensions, |
| 125 | + ) |
| 126 | + sys.exit(0) |
34 | 127 |
|
35 |
| - cmd = ["clang-format", "-i"] + c_files + h_files |
| 128 | + if consume_arg("--format"): |
| 129 | + cmd = ["clang-format", "-i"] + [ |
| 130 | + str(file) for file in Path("./src_c/").glob("**/*.[c|h]") |
| 131 | + ] |
36 | 132 | print(shlex.join(cmd))
|
37 | 133 | subprocess.call(cmd)
|
38 | 134 |
|
39 | 135 | cmd = ["black", "."]
|
40 | 136 | print(shlex.join(cmd))
|
41 | 137 | subprocess.call(cmd)
|
42 | 138 |
|
43 |
| - sys.exit(0) |
| 139 | + run_tests = consume_arg("--test") |
44 | 140 |
|
45 | 141 | build()
|
| 142 | + |
| 143 | + if run_tests: |
| 144 | + cmd = ["python", "-m", "unittest"] |
| 145 | + print(shlex.join(cmd)) |
| 146 | + subprocess.call(cmd) |
0 commit comments