-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextensions.py
More file actions
145 lines (118 loc) · 4.72 KB
/
extensions.py
File metadata and controls
145 lines (118 loc) · 4.72 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
import os
import platform
import shutil
from pathlib import Path
from subprocess import check_call
import numpy as np
import sys
import urllib.request
sys.dont_write_bytecode = True
from setuptools import Extension
from setuptools.command.build_ext import build_ext
from setuptools.command.build_ext import build_ext
from importlib.machinery import EXTENSION_SUFFIXES
def get_shared_lib_ext():
if sys.platform.startswith("linux"):
return ".so"
elif sys.platform.startswith("darwin"):
return ".dylib"
else:
return ".dll"
def create_directory(path: Path):
if path.exists():
shutil.rmtree(path)
path.mkdir(exist_ok=True, parents=True)
return path
def mkdir(dir):
if platform.system() == "Windows":
return f"mkdir {dir}"
else:
return f"mkdir -p {dir}"
class OptBuildExtension(Extension):
def __init__(self, name: str, version: str):
super().__init__(name, sources=[])
# Source dir should be at the root directory
self.source_dir = Path(__file__).parent.absolute()
self.version = version
class OptBuild(build_ext):
def run(self):
try:
check_call(["cmake", "--version"])
except OSError:
raise RuntimeError("CMake must be installed")
if platform.system() not in ("Windows", "Linux", "Darwin"):
raise RuntimeError(f"Unsupported os: {platform.system()}")
for ext in self.extensions:
if isinstance(ext, OptBuildExtension):
self.build_extension(ext)
@property
def config(self):
return "Debug" if self.debug else "Release"
def build_cma(self):
if platform.system() == "Windows":
return 'cmake -DLIBCMAES_BUILD_EXAMPLES=OFF -G "Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release'
else:
return "cmake -DLIBCMAES_BUILD_EXAMPLES=OFF .. && make -j"
def build_gob(self, lib_name, pkg_name):
if platform.system() == "Windows":
return f'cmake -DPython_EXECUTABLE={sys.executable} -DNUMPY_INCLUDE_DIRS={np.get_include()} -DEXT_NAME={lib_name} -DCYTHON_CPP_FILE={pkg_name}.cc .. -G "Visual Studio 17 2022" -A x64 && cmake --build . --config Release'
else:
return f"cmake -DPython_EXECUTABLE={sys.executable} -DNUMPY_INCLUDE_DIRS={np.get_include()} -DEXT_NAME={lib_name} -DCYTHON_CPP_FILE={pkg_name}.cc .. && make -j"
def shared_lib_path(self, lib_name):
if platform.system() == "Windows":
return f"Release/{lib_name}{get_shared_lib_ext()}"
else:
return f"lib{lib_name}{get_shared_lib_ext()}"
def build_extension(self, ext: Extension):
cython_src_dir = Path("gob/optimizers/cpp_optimizers")
# Copy libcmaes files
os.system(
f"cd {cython_src_dir} "
"&& rm -rf libcmaes "
"&& git clone https://github.com/gaetanserre/libcmaes.git "
"&& cd libcmaes "
f"&& {mkdir('build')} "
"&& cd build "
f"&& {self.build_cma()} "
"&& cd ../.. "
"&& cp -r libcmaes/include/libcmaes include "
"&& cp -r libcmaes/build/include/libcmaes/* include/libcmaes "
f"&& cd src && {mkdir('libcmaes')} && cd .. "
"&& cp libcmaes/src/**.cc src/libcmaes "
"&& rm -rf libcmaes"
)
# Copy GLPK files
urllib.request.urlretrieve(
"https://mirrors.ocf.berkeley.edu/gnu/glpk/glpk-5.0.tar.gz",
Path(cython_src_dir, "glpk-5.0.tar.gz"),
)
os.system(
f"cd {cython_src_dir} "
"&& tar -xvf glpk-5.0.tar.gz "
"&& rm glpk-5.0.tar.gz"
)
ext_dir = Path(self.get_ext_fullpath(ext.name)).parent.absolute()
create_directory(ext_dir)
pkg_name = "cpp_optimizers"
ext_suffix = EXTENSION_SUFFIXES[0]
lib_name = ".".join((pkg_name + ext_suffix).split(".")[:-1])
pkg_ext = ".pyd" if platform.system() == "Windows" else ".so"
# Compile the Cython file
os.system(
f"cython --cplus -3 {cython_src_dir}/{pkg_name}.pyx -o {cython_src_dir}/{pkg_name}.cc"
)
# Compile the C++ files
os.system(
f"cd {cython_src_dir} "
"&& ls -la .. "
f"&& rm -rf ../*{pkg_ext} "
f"&& {mkdir('build')} "
"&& cd build "
f"&& {self.build_gob(lib_name, pkg_name)} "
f"&& mv {self.shared_lib_path(lib_name)} ../../{lib_name}{pkg_ext} "
f"&& cd {ext.source_dir.as_posix()}"
)
# Clean up
os.system(f"rm -rf {cython_src_dir / 'build'}")
# Copy files to the build directory
os.system(f"cp -r gob {ext_dir}")