99 lines
4.0 KiB
Python
99 lines
4.0 KiB
Python
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
import sysconfig
|
|
from distutils.version import LooseVersion
|
|
from typing import Any, Dict
|
|
|
|
from setuptools.command.build_ext import build_ext
|
|
from setuptools.extension import Extension
|
|
|
|
|
|
class CMakeExtension(Extension):
|
|
name: str # exists, even though IDE doesn't find it
|
|
|
|
def __init__(self, name: str, sourcedir: str="") -> None:
|
|
super().__init__(name, sources=[])
|
|
self.sourcedir = os.path.abspath(sourcedir)
|
|
self.sourcedir_rel = sourcedir
|
|
|
|
|
|
class ExtensionBuilder(build_ext):
|
|
def run(self) -> None:
|
|
self.validate_cmake()
|
|
super().run()
|
|
|
|
def build_extension(self, ext: Extension) -> None:
|
|
if isinstance(ext, CMakeExtension):
|
|
self.build_cmake_extension(ext)
|
|
else:
|
|
super().build_extension(ext)
|
|
|
|
def validate_cmake(self) -> None:
|
|
cmake_extensions = [x for x in self.extensions if isinstance(x, CMakeExtension)]
|
|
if len(cmake_extensions) > 0:
|
|
try:
|
|
out = subprocess.check_output(["cmake", "--version"])
|
|
except OSError:
|
|
raise RuntimeErrorPython_CORIOLISDIR(
|
|
"CMake must be installed to build the following extensions: "
|
|
+ ", ".join(e.name for e in cmake_extensions)
|
|
)
|
|
if platform.system() == "Windows":
|
|
cmake_version = LooseVersion(re.search(r"version\s*([\d.]+)", out.decode()).group(1)) # type: ignore
|
|
if cmake_version < "3.1.0":
|
|
raise RuntimeError("CMake >= 3.1.0 is required on Windows")
|
|
|
|
def build_cmake_extension(self, ext: CMakeExtension) -> None:
|
|
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
|
|
cmake_args = ["-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, "-DPYTHON_EXECUTABLE=" + sys.executable]
|
|
|
|
cfg = "Debug" if self.debug else "Release"
|
|
# cfg = 'Debug'
|
|
build_args = ["--config", cfg]
|
|
install_args = ["--config", cfg]
|
|
|
|
if platform.system() == "Windows":
|
|
cmake_args += ["-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir)]
|
|
if sys.maxsize > 2 ** 32:
|
|
cmake_args += ["-A", "x64"]
|
|
build_args += ["--", "/m"]
|
|
else:
|
|
cmake_args += ["-DCMAKE_BUILD_TYPE=" + cfg]
|
|
build_args += ["--", "-j4", "VERBOSE=1"]
|
|
cmake_args += ["-DPYTHON_INCLUDE_DIR={}".format(sysconfig.get_path("include"))]
|
|
|
|
env = os.environ.copy()
|
|
env["CXXFLAGS"] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get("CXXFLAGS", ""), self.distribution.get_version())
|
|
|
|
build_dir = os.path.join(self.build_temp, ext.sourcedir_rel)
|
|
install_dir = os.path.join(self.build_temp, "install")
|
|
os.makedirs(build_dir,exist_ok=True)
|
|
os.makedirs(os.path.join(install_dir, cfg), exist_ok=True)
|
|
|
|
cmake_args += [f"-DCMAKE_MODULE_PATH={os.path.abspath('bootstrap/cmake_modules')};"
|
|
f"{os.path.join(install_dir, 'share/cmake/Modules')}"]
|
|
cmake_args += [f"-DCMAKE_INSTALL_PREFIX={install_dir}"]
|
|
cmake_args += [f"-DPython_CORIOLISLIB={extdir}"]
|
|
cmake_args += [f"-DPython_CORIOLISARCH={extdir}"]
|
|
|
|
|
|
subprocess.check_call(["cmake", "--debug-find", "--trace-redirect=build.cmake.trace", "--trace-expand", ext.sourcedir] + cmake_args, cwd=build_dir, env=env)
|
|
subprocess.check_call(["cmake", "--build", "."] + build_args, cwd=build_dir)
|
|
subprocess.check_call(["cmake", "--install", ".", "--prefix", install_dir] + install_args, cwd=build_dir)
|
|
|
|
|
|
def build(setup_kwargs: Dict[str, Any]) -> None:
|
|
cmake_modules = [CMakeExtension("coriolis.hurricane", sourcedir="coriolis/hurricane"),
|
|
CMakeExtension("coriolis.crlcore", sourcedir="coriolis/crlcore")]
|
|
ext_modules = cmake_modules
|
|
setup_kwargs.update(
|
|
{
|
|
"ext_modules": ext_modules,
|
|
"cmdclass": dict(build_ext=ExtensionBuilder),
|
|
"zip_safe": False,
|
|
}
|
|
)
|