From 32c323aff71e9aaca2ab2f79515d98c6f0bbe540 Mon Sep 17 00:00:00 2001 From: Catherine Date: Thu, 1 Jun 2023 18:17:44 +0000 Subject: [PATCH 1/2] _toolchain.cxx: remove. This is causing issues on Python 3.12 and in any case should be based on the Python `ziglang` package instead of this cursed setuptools hack. --- amaranth/_toolchain/cxx.py | 73 ------------------------------------- tests/test_toolchain_cxx.py | 68 ---------------------------------- 2 files changed, 141 deletions(-) delete mode 100644 amaranth/_toolchain/cxx.py delete mode 100644 tests/test_toolchain_cxx.py diff --git a/amaranth/_toolchain/cxx.py b/amaranth/_toolchain/cxx.py deleted file mode 100644 index a2b700646..000000000 --- a/amaranth/_toolchain/cxx.py +++ /dev/null @@ -1,73 +0,0 @@ -import tempfile -import sysconfig -import warnings -import os.path - - -__all__ = ["build_cxx"] - - -def build_cxx(*, cxx_sources, output_name, include_dirs, macros): - build_dir = tempfile.TemporaryDirectory(prefix="amaranth_cxx_") - - cwd = os.getcwd() - try: - # Unfortunately, `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) - - with warnings.catch_warnings(): - warnings.filterwarnings(action="ignore", category=DeprecationWarning) - # This emits a DeprecationWarning on Python 3.10. - import setuptools - from distutils import ccompiler - cc_driver = 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) diff --git a/tests/test_toolchain_cxx.py b/tests/test_toolchain_cxx.py deleted file mode 100644 index 48f674ef5..000000000 --- a/tests/test_toolchain_cxx.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -import ctypes -import tempfile -import unittest - -from amaranth._toolchain.cxx import * - - -class ToolchainCxxTestCase(unittest.TestCase): - def setUp(self): - self.include_dir = None - self.build_dir = None - - def tearDown(self): - if self.include_dir: - self.include_dir.cleanup() - if self.build_dir: - self.build_dir.cleanup() - - def test_filename(self): - self.build_dir, filename = build_cxx( - cxx_sources={"test.cc": ""}, - output_name="answer", - include_dirs=[], - macros=[], - ) - self.assertTrue(filename.startswith("answer")) - - def test_simple(self): - self.build_dir, filename = build_cxx( - cxx_sources={"test.cc": """ - extern "C" int answer() { return 42; } - """}, - output_name="answer", - include_dirs=[], - macros=[], - ) - library = ctypes.cdll.LoadLibrary(os.path.join(self.build_dir.name, filename)) - self.assertEqual(library.answer(), 42) - - def test_macro(self): - self.build_dir, filename = build_cxx( - cxx_sources={"test.cc": """ - extern "C" int answer() { return ANSWER; } - """}, - output_name="answer", - include_dirs=[], - macros=["ANSWER=42"], - ) - library = ctypes.cdll.LoadLibrary(os.path.join(self.build_dir.name, filename)) - self.assertEqual(library.answer(), 42) - - def test_include(self): - self.include_dir = tempfile.TemporaryDirectory(prefix="amaranth_hxx_") - with open(os.path.join(self.include_dir.name, "answer.h"), "w") as f: - f.write("#define ANSWER 42") - - self.build_dir, filename = build_cxx( - cxx_sources={"test.cc": """ - #include - extern "C" int answer() { return ANSWER; } - """}, - output_name="answer", - include_dirs=[self.include_dir.name], - macros=[], - ) - library = ctypes.cdll.LoadLibrary(os.path.join(self.build_dir.name, filename)) - self.assertEqual(library.answer(), 42) From 2c0f844b2cddaebd271927dc5dd54a0a16fcceed Mon Sep 17 00:00:00 2001 From: Catherine Date: Thu, 1 Jun 2023 18:22:24 +0000 Subject: [PATCH 2/2] hdl.dsl: py3.12+: turn off heuristic warning on `~True` and `~False`. There is now an upstream deprecation warning for the same. We don't have to duplicate it. --- amaranth/hdl/dsl.py | 4 +++- tests/test_hdl_dsl.py | 34 ++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/amaranth/hdl/dsl.py b/amaranth/hdl/dsl.py index feabef108..7edb03bc9 100644 --- a/amaranth/hdl/dsl.py +++ b/amaranth/hdl/dsl.py @@ -3,6 +3,7 @@ from functools import wraps from enum import Enum import warnings +import sys from .._utils import flatten, bits_for from .. import tracer @@ -210,7 +211,8 @@ def _set_ctrl(self, name, data): def _check_signed_cond(self, cond): cond = Value.cast(cond) - if cond.shape().signed: + if sys.version_info < (3, 12, 0) and cond.shape().signed: + # TODO(py3.11): remove; ~True is a warning in 3.12+, finally! warnings.warn("Signed values in If/Elif conditions usually result from inverting " "Python booleans with ~, which leads to unexpected results. " "Replace `~flag` with `not flag`. (If this is a false positive, " diff --git a/tests/test_hdl_dsl.py b/tests/test_hdl_dsl.py index d08878ecc..9fc210ff5 100644 --- a/tests/test_hdl_dsl.py +++ b/tests/test_hdl_dsl.py @@ -1,5 +1,6 @@ # amaranth: UnusedElaboratable=no +import sys from collections import OrderedDict from amaranth.hdl.ast import * @@ -324,27 +325,28 @@ def test_If_wide(self): ) """) - def test_If_signed_suspicious(self): - m = Module() - with self.assertWarnsRegex(SyntaxWarning, - (r"^Signed values in If\/Elif conditions usually result from inverting Python " + if sys.version_info < (3, 12): # upstream warning in 3.12! + def test_If_signed_suspicious(self): + m = Module() + with self.assertWarnsRegex(SyntaxWarning, + r"^Signed values in If\/Elif conditions usually result from inverting Python " r"booleans with ~, which leads to unexpected results\. Replace `~flag` with " r"`not flag`\. \(If this is a false positive, silence this warning with " - r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")): - with m.If(~True): - pass + r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$"): + with m.If(~True): + pass - def test_Elif_signed_suspicious(self): - m = Module() - with m.If(0): - pass - with self.assertWarnsRegex(SyntaxWarning, - (r"^Signed values in If\/Elif conditions usually result from inverting Python " + def test_Elif_signed_suspicious(self): + m = Module() + with m.If(0): + pass + with self.assertWarnsRegex(SyntaxWarning, + r"^Signed values in If\/Elif conditions usually result from inverting Python " r"booleans with ~, which leads to unexpected results\. Replace `~flag` with " r"`not flag`\. \(If this is a false positive, silence this warning with " - r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")): - with m.Elif(~True): - pass + r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$"): + with m.Elif(~True): + pass def test_if_If_Elif_Else(self): m = Module()