148 lines
6.5 KiB
Python
148 lines
6.5 KiB
Python
import io
|
|
import glob
|
|
import ninja
|
|
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
from distutils.version import LooseVersion
|
|
from distutils.dir_util import copy_tree, remove_tree
|
|
from distutils.sysconfig import get_python_inc
|
|
from distutils import sysconfig
|
|
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 RuntimeError(
|
|
"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 = []
|
|
|
|
ninja_executable_path = os.path.join(ninja.BIN_DIR, "ninja")
|
|
cmake_args += ["-GNinja","-DCMAKE_MAKE_PROGRAM:FILEPATH=" + ninja_executable_path]
|
|
|
|
cfg = "Debug" if self.debug else "Release"
|
|
# cfg = 'Debug'
|
|
build_args = ["--config", cfg]
|
|
install_args = ["--config", cfg]
|
|
|
|
cmake_args += ["-DCMAKE_BUILD_TYPE=" + cfg]
|
|
if platform.system() == "Windows":
|
|
if sys.maxsize > 2 ** 32:
|
|
cmake_args += ["-A", "x64"]
|
|
|
|
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(extdir, 'Coriolis')
|
|
os.makedirs(build_dir,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={install_dir}"]
|
|
cmake_args += [f"-DPython_CORIOLISARCH={install_dir}"]
|
|
cmake_args += [f"-DSYS_CONF_DIR={install_dir}"]
|
|
cmake_args += [f"-DCORIOLIS_TOP={install_dir}"]
|
|
cmake_args += [f"-DCORIOLIS_USER_TOP={install_dir}"]
|
|
|
|
cmake_args += [f"-DPython_EXECUTABLE={sys.executable}"]
|
|
|
|
cmake_args += ["-DPOETRY=1"]
|
|
cmake_args += ["-DWITH_QT5=1"]
|
|
cmake_args += ["-DCMAKE_BUILD_RPATH_USE_ORIGIN=1"]
|
|
cmake_args += ["-DCMAKE_SKIP_BUILD_RPATH=FALSE"]
|
|
cmake_args += ["-DCMAKE_BUILD_WITH_INSTALL_RPATH=FALSE"]
|
|
cmake_args += ["-DCMAKE_INSTALL_RPATH='$ORIGIN/lib:$ORIGIN'"]
|
|
cmake_args += ["-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE"]
|
|
|
|
|
|
print(f"Using cmake args: {cmake_args}")
|
|
subprocess.check_call(["cmake", "--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)
|
|
if os.path.exists(os.path.join(install_dir, "bin")):
|
|
copy_tree(os.path.join(install_dir, "bin"), os.path.join(install_dir,"data/bin"))
|
|
remove_tree(os.path.join(install_dir, "bin"))
|
|
proc = subprocess.Popen(['file'] + glob.glob(os.path.join(install_dir,"data/bin/*")), stdout=subprocess.PIPE)
|
|
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
|
|
if 'ELF' in line: #TODO support other OSs
|
|
f = line.split(':')[0]
|
|
print(f"fixing up {f}")
|
|
subprocess.check_call(["patchelf", "--set-rpath", '$ORIGIN/../../lib', f])
|
|
|
|
# Remove docs
|
|
if os.path.exists(os.path.join(install_dir, "share", "doc")):
|
|
remove_tree(os.path.join(install_dir, "share", "doc"))
|
|
|
|
def build(setup_kwargs: Dict[str, Any]) -> None:
|
|
cmake_modules = [
|
|
CMakeExtension("coloquinte", sourcedir="coloquinte"),
|
|
CMakeExtension("Hurricane", sourcedir="hurricane"),
|
|
CMakeExtension("crlcore", sourcedir="crlcore"),
|
|
CMakeExtension("flute", sourcedir="flute"),
|
|
CMakeExtension("etesian", sourcedir="etesian"),
|
|
CMakeExtension("anabatic", sourcedir="anabatic"),
|
|
CMakeExtension("katana", sourcedir="katana"),
|
|
CMakeExtension("equinox", sourcedir="equinox"),
|
|
CMakeExtension("solstice", sourcedir="solstice"),
|
|
CMakeExtension("oroshi", sourcedir="oroshi"),
|
|
CMakeExtension("bora", sourcedir="bora"),
|
|
CMakeExtension("karakaze", sourcedir="karakaze"),
|
|
#CMakeExtension("knik", sourcedir="knik"),
|
|
#CMakeExtension("unicorn", sourcedir="unicorn"),
|
|
CMakeExtension("tutorial", sourcedir="tutorial"),
|
|
CMakeExtension("cumulus", sourcedir="cumulus"),
|
|
CMakeExtension("stratus1", sourcedir="stratus1"),
|
|
CMakeExtension("documentation", sourcedir="documentation"),
|
|
CMakeExtension("unittests", sourcedir="unittests")
|
|
]
|
|
|
|
ext_modules = cmake_modules
|
|
setup_kwargs.update(
|
|
{
|
|
"ext_modules": ext_modules,
|
|
"cmdclass": dict(build_ext=ExtensionBuilder),
|
|
"zip_safe": False,
|
|
}
|
|
)
|