forked from stlehmann/pyads
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsetup.py
120 lines (94 loc) · 3.45 KB
/
setup.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
from pathlib import Path
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.build_py import build_py
from wheel.bdist_wheel import bdist_wheel
import sys
import sysconfig
import os
import subprocess
src_folder = Path(__file__).parent.absolute() / "src"
# ^ This will be on PATH for editable install
adslib_folder = Path(__file__).parent.absolute() / "adslib"
adslib_file = src_folder / "adslib.so"
class CustomBuildPy(build_py):
"""Custom command for `build_py`.
This command class is used because it is always run, also for an editable install.
"""
@classmethod
def compile_adslib(cls) -> bool:
"""Return `True` if adslib was actually compiled."""
if cls.platform_is_unix():
cls._clean_library()
cls._compile_library()
return True
return False
@staticmethod
def _compile_library():
"""Use `make` to build adslib - build is done in-place."""
# Produce `adslib.so`:
subprocess.call(["make", "-C", "adslib"])
@staticmethod
def _clean_library():
"""Remove all compilation artifacts."""
patterns = (
"*.a",
"**/*.o",
"*.bin",
"*.so",
)
for pattern in patterns:
for file in adslib_folder.glob(pattern):
os.remove(file)
if adslib_file.is_file():
os.remove(adslib_file)
@staticmethod
def platform_is_unix():
return sys.platform.startswith("linux") or sys.platform.startswith("darwin")
def run(self):
if self.compile_adslib():
# Move .so file from Git submodule into src/ to have it on PATH:
self.move_file(
str(adslib_folder / "adslib.so"),
str(adslib_file),
)
super().run()
class CustomInstall(install):
"""Install compiled adslib (but only for Linux)."""
def run(self):
if CustomBuildPy.platform_is_unix():
adslib_dest = Path(self.install_lib)
if not adslib_dest.exists():
adslib_dest.mkdir(parents=True)
self.copy_file(
str(adslib_file),
str(adslib_dest),
)
super().run()
class CustomBDistWheel(bdist_wheel):
"""Manually mark our wheel for a specific platform."""
def get_tag(self):
"""
See https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/
"""
impl_tag = "py2.py3" # Same wheel across Python versions
abi_tag = "none" # Same wheeel across ABI versions (not a C-extension)
# But we need to differentiate on the platform for the compiled adslib:
plat_tag = sysconfig.get_platform().replace("-", "_").replace(".", "_")
if plat_tag.startswith("linux_"):
# But the basic Linux prefix is deprecated, use new scheme instead:
plat_tag = "manylinux_2_24" + plat_tag[5:]
# MacOS platform tags area already okay
# We also keep Windows tags in place, instead of using `any`, to prevent an
# obscure Linux platform to getting a wheel without adslib source
return impl_tag, abi_tag, plat_tag
# noinspection PyTypeChecker
setup(
cmdclass={
"build_py": CustomBuildPy,
"install": CustomInstall,
"bdist_wheel": CustomBDistWheel,
},
)
# See `pyproject.toml` for all package information
# Also see `MANIFEST.in`