
The distutils module from the standard library is deprecated and will be removed in Python 3.12, and PEP 632 recommends using distutils.ccompiler from setuptools, instead. This code should eventually be rewritten to use zig-pypi, but for now this suffices.
68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
import tempfile
|
|
import sysconfig
|
|
import os.path
|
|
from setuptools import distutils
|
|
|
|
|
|
__all__ = ["build_cxx"]
|
|
|
|
|
|
def build_cxx(*, cxx_sources, output_name, include_dirs, macros):
|
|
build_dir = tempfile.TemporaryDirectory(prefix="nmigen_cxx_")
|
|
|
|
cwd = os.getcwd()
|
|
try:
|
|
# Unforuntately, `ccompiler.compile` assumes the paths are relative, and interprets
|
|
# the directory name of the source path specially. That makes it necessary to build in
|
|
# the output directory directly.
|
|
os.chdir(build_dir.name)
|
|
|
|
cc_driver = distutils.ccompiler.new_compiler()
|
|
cc_driver.output_dir = "."
|
|
|
|
cc = sysconfig.get_config_var("CC")
|
|
cxx = sysconfig.get_config_var("CXX")
|
|
cflags = sysconfig.get_config_var("CCSHARED")
|
|
ld_flags = sysconfig.get_config_var("LDSHARED")
|
|
ld_cxxflags = sysconfig.get_config_var("LDCXXSHARED")
|
|
if ld_cxxflags is None:
|
|
# PyPy doesn't have LDCXXSHARED. Glue it together from CXX and LDSHARED and hope that
|
|
# the result actually works; not many good options here.
|
|
ld_cxxflags = " ".join([cxx.split()[0], *ld_flags.split()[1:]])
|
|
cc_driver.set_executables(
|
|
compiler=f"{cc} {cflags}",
|
|
compiler_so=f"{cc} {cflags}",
|
|
compiler_cxx=f"{cxx} {cflags}",
|
|
linker_so=ld_cxxflags,
|
|
)
|
|
|
|
# Sometimes CCompiler is modified to have additional executable entries for compiling and
|
|
# linking CXX shared objects (e.g. on Gentoo). These executables have to be set then.
|
|
try:
|
|
cc_driver.set_executables(
|
|
compiler_so_cxx=f"{cxx} {cflags}",
|
|
linker_so_cxx=ld_cxxflags,
|
|
)
|
|
except:
|
|
pass
|
|
|
|
for include_dir in include_dirs:
|
|
cc_driver.add_include_dir(include_dir)
|
|
for macro in macros:
|
|
cc_driver.define_macro(macro)
|
|
for cxx_filename, cxx_source in cxx_sources.items():
|
|
with open(cxx_filename, "w") as f:
|
|
f.write(cxx_source)
|
|
|
|
cxx_filenames = list(cxx_sources.keys())
|
|
obj_filenames = cc_driver.object_filenames(cxx_filenames)
|
|
so_filename = cc_driver.shared_object_filename(output_name)
|
|
|
|
cc_driver.compile(cxx_filenames)
|
|
cc_driver.link_shared_object(obj_filenames, output_filename=so_filename, target_lang="c++")
|
|
|
|
return build_dir, so_filename
|
|
|
|
finally:
|
|
os.chdir(cwd)
|