Add iptable-parser as submodule

This commit is contained in:
infidel
2023-10-30 14:40:43 +07:00
parent 64c9e9c11b
commit be27c0882e
35887 changed files with 2661509 additions and 69 deletions

View File

@@ -0,0 +1,9 @@
def f2py_build_generator(name):
if name == "meson":
from ._meson import MesonBackend
return MesonBackend
elif name == "distutils":
from ._distutils import DistutilsBackend
return DistutilsBackend
else:
raise ValueError(f"Unknown backend: {name}")

View File

@@ -0,0 +1,46 @@
from __future__ import annotations
from abc import ABC, abstractmethod
class Backend(ABC):
def __init__(
self,
modulename,
sources,
extra_objects,
build_dir,
include_dirs,
library_dirs,
libraries,
define_macros,
undef_macros,
f2py_flags,
sysinfo_flags,
fc_flags,
flib_flags,
setup_flags,
remove_build_dir,
extra_dat,
):
self.modulename = modulename
self.sources = sources
self.extra_objects = extra_objects
self.build_dir = build_dir
self.include_dirs = include_dirs
self.library_dirs = library_dirs
self.libraries = libraries
self.define_macros = define_macros
self.undef_macros = undef_macros
self.f2py_flags = f2py_flags
self.sysinfo_flags = sysinfo_flags
self.fc_flags = fc_flags
self.flib_flags = flib_flags
self.setup_flags = setup_flags
self.remove_build_dir = remove_build_dir
self.extra_dat = extra_dat
@abstractmethod
def compile(self) -> None:
"""Compile the wrapper."""
pass

View File

@@ -0,0 +1,75 @@
from ._backend import Backend
from numpy.distutils.core import setup, Extension
from numpy.distutils.system_info import get_info
from numpy.distutils.misc_util import dict_append
from numpy.exceptions import VisibleDeprecationWarning
import os
import sys
import shutil
import warnings
class DistutilsBackend(Backend):
def __init__(sef, *args, **kwargs):
warnings.warn(
"distutils has been deprecated since NumPy 1.26."
"Use the Meson backend instead, or generate wrappers"
"without -c and use a custom build script",
VisibleDeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwargs)
def compile(self):
num_info = {}
if num_info:
self.include_dirs.extend(num_info.get("include_dirs", []))
ext_args = {
"name": self.modulename,
"sources": self.sources,
"include_dirs": self.include_dirs,
"library_dirs": self.library_dirs,
"libraries": self.libraries,
"define_macros": self.define_macros,
"undef_macros": self.undef_macros,
"extra_objects": self.extra_objects,
"f2py_options": self.f2py_flags,
}
if self.sysinfo_flags:
for n in self.sysinfo_flags:
i = get_info(n)
if not i:
print(
f"No {repr(n)} resources found"
"in system (try `f2py --help-link`)"
)
dict_append(ext_args, **i)
ext = Extension(**ext_args)
sys.argv = [sys.argv[0]] + self.setup_flags
sys.argv.extend(
[
"build",
"--build-temp",
self.build_dir,
"--build-base",
self.build_dir,
"--build-platlib",
".",
"--disable-optimization",
]
)
if self.fc_flags:
sys.argv.extend(["config_fc"] + self.fc_flags)
if self.flib_flags:
sys.argv.extend(["build_ext"] + self.flib_flags)
setup(ext_modules=[ext])
if self.remove_build_dir and os.path.exists(self.build_dir):
print(f"Removing build directory {self.build_dir}")
shutil.rmtree(self.build_dir)

View File

@@ -0,0 +1,157 @@
from __future__ import annotations
import errno
import shutil
import subprocess
from pathlib import Path
from ._backend import Backend
from string import Template
import warnings
class MesonTemplate:
"""Template meson build file generation class."""
def __init__(
self,
modulename: str,
sources: list[Path],
deps: list[str],
object_files: list[Path],
linker_args: list[str],
c_args: list[str],
build_type: str,
):
self.modulename = modulename
self.build_template_path = (
Path(__file__).parent.absolute() / "meson.build.template"
)
self.sources = sources
self.deps = deps
self.substitutions = {}
self.objects = object_files
self.pipeline = [
self.initialize_template,
self.sources_substitution,
self.deps_substitution,
]
self.build_type = build_type
def meson_build_template(self) -> str:
if not self.build_template_path.is_file():
raise FileNotFoundError(
errno.ENOENT,
"Meson build template"
f" {self.build_template_path.absolute()}"
" does not exist.",
)
return self.build_template_path.read_text()
def initialize_template(self) -> None:
self.substitutions["modulename"] = self.modulename
self.substitutions["buildtype"] = self.build_type
def sources_substitution(self) -> None:
indent = " " * 21
self.substitutions["source_list"] = f",\n{indent}".join(
[f"'{source}'" for source in self.sources]
)
def deps_substitution(self) -> None:
indent = " " * 21
self.substitutions["dep_list"] = f",\n{indent}".join(
[f"dependency('{dep}')" for dep in self.deps]
)
def generate_meson_build(self):
for node in self.pipeline:
node()
template = Template(self.meson_build_template())
return template.substitute(self.substitutions)
class MesonBackend(Backend):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.dependencies = self.extra_dat.get("dependencies", [])
self.meson_build_dir = "bbdir"
self.build_type = (
"debug" if any("debug" in flag for flag in self.fc_flags) else "release"
)
def _move_exec_to_root(self, build_dir: Path):
walk_dir = Path(build_dir) / self.meson_build_dir
path_objects = walk_dir.glob(f"{self.modulename}*.so")
for path_object in path_objects:
shutil.move(path_object, Path.cwd())
def _get_build_command(self):
return [
"meson",
"setup",
self.meson_build_dir,
]
def write_meson_build(self, build_dir: Path) -> None:
"""Writes the meson build file at specified location"""
meson_template = MesonTemplate(
self.modulename,
self.sources,
self.dependencies,
self.extra_objects,
self.flib_flags,
self.fc_flags,
self.build_type,
)
src = meson_template.generate_meson_build()
Path(build_dir).mkdir(parents=True, exist_ok=True)
meson_build_file = Path(build_dir) / "meson.build"
meson_build_file.write_text(src)
return meson_build_file
def run_meson(self, build_dir: Path):
completed_process = subprocess.run(self._get_build_command(), cwd=build_dir)
if completed_process.returncode != 0:
raise subprocess.CalledProcessError(
completed_process.returncode, completed_process.args
)
completed_process = subprocess.run(
["meson", "compile", "-C", self.meson_build_dir], cwd=build_dir
)
if completed_process.returncode != 0:
raise subprocess.CalledProcessError(
completed_process.returncode, completed_process.args
)
def compile(self) -> None:
self.sources = _prepare_sources(self.modulename, self.sources, self.build_dir)
self.write_meson_build(self.build_dir)
self.run_meson(self.build_dir)
self._move_exec_to_root(self.build_dir)
def _prepare_sources(mname, sources, bdir):
extended_sources = sources.copy()
Path(bdir).mkdir(parents=True, exist_ok=True)
# Copy sources
for source in sources:
shutil.copy(source, bdir)
generated_sources = [
Path(f"{mname}module.c"),
Path(f"{mname}-f2pywrappers2.f90"),
Path(f"{mname}-f2pywrappers.f"),
]
bdir = Path(bdir)
for generated_source in generated_sources:
if generated_source.exists():
shutil.copy(generated_source, bdir / generated_source.name)
extended_sources.append(generated_source.name)
generated_source.unlink()
extended_sources = [
Path(source).name
for source in extended_sources
if not Path(source).suffix == ".pyf"
]
return extended_sources

View File

@@ -0,0 +1,42 @@
project('${modulename}',
['c', 'fortran'],
version : '0.1',
meson_version: '>= 1.1.0',
default_options : [
'warning_level=1',
'buildtype=${buildtype}'
])
py = import('python').find_installation(pure: false)
py_dep = py.dependency()
incdir_numpy = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
check : true
).stdout().strip()
incdir_f2py = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
check : true
).stdout().strip()
inc_np = include_directories(incdir_numpy)
np_dep = declare_dependency(include_directories: inc_np)
incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src'
inc_f2py = include_directories(incdir_f2py)
fortranobject_c = incdir_f2py / 'fortranobject.c'
inc_np = include_directories(incdir_numpy, incdir_f2py)
py.extension_module('${modulename}',
[
${source_list},
fortranobject_c
],
include_directories: [inc_np],
dependencies : [
py_dep,
${dep_list}
],
install : true)