Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions mypy/test/testmypyc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@

from __future__ import annotations

import filecmp
import os
from unittest import TestCase

import mypy
import mypyc


class MypycTest(TestCase):
def test_using_mypyc(self) -> None:
if os.getenv("TEST_MYPYC", None) == "1":
assert not mypy.__file__.endswith(".py"), "Expected to find a mypyc-compiled version"

def test_shared_files_consistent(self) -> None:
if os.getenv("TEST_MYPYC", None) != "1":
mypyc_path = mypyc.__path__[0]
for f in ["build_setup.py"]:
assert filecmp.cmp(
os.path.join(mypyc_path, f),
os.path.join(mypyc_path, "lib-rt", f),
shallow=False,
), f"Shared files inconsistent, run cp mypyc/{f} mypyc/lib-rt"
2 changes: 1 addition & 1 deletion mypy_self_check.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pretty = True
always_false = MYPYC
plugins = mypy.plugins.proper_plugin
python_version = 3.10
exclude = mypy/typeshed/|mypyc/test-data/
exclude = mypy/typeshed/|mypyc/test-data/|mypyc/lib-rt/
enable_error_code = ignore-without-code,redundant-expr
enable_incomplete_feature = PreciseTupleTypes
show_error_code_links = True
Expand Down
4 changes: 4 additions & 0 deletions mypyc/build_setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# This file must have the same content for mypyc/build_setup.py and lib-rt/build_setup.py,
# it exists to work around absence of support for per-file compile flags in setuptools.
# The version in mypyc/ is the source of truth, and should be copied to lib-rt if modified.

import os
import platform
import sys
Expand Down
76 changes: 76 additions & 0 deletions mypyc/lib-rt/build_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# This file must have the same content for mypyc/build_setup.py and lib-rt/build_setup.py,
# it exists to work around absence of support for per-file compile flags in setuptools.
# The version in mypyc/ is the source of truth, and should be copied to lib-rt if modified.

import os
import platform
import sys

try:
# Import setuptools so that it monkey-patch overrides distutils
import setuptools # noqa: F401
except ImportError:
pass

if sys.version_info >= (3, 12):
# From setuptools' monkeypatch
from distutils import ccompiler # type: ignore[import-not-found]
else:
from distutils import ccompiler

EXTRA_FLAGS_PER_COMPILER_TYPE_PER_PATH_COMPONENT = {
"unix": {
"base64/arch/ssse3": ["-mssse3"],
"base64/arch/sse41": ["-msse4.1"],
"base64/arch/sse42": ["-msse4.2"],
"base64/arch/avx2": ["-mavx2"],
"base64/arch/avx": ["-mavx"],
},
"msvc": {
"base64/arch/sse42": ["/arch:SSE4.2"],
"base64/arch/avx2": ["/arch:AVX2"],
"base64/arch/avx": ["/arch:AVX"],
},
}

ccompiler.CCompiler.__spawn = ccompiler.CCompiler.spawn # type: ignore[attr-defined]
X86_64 = platform.machine() in ("x86_64", "AMD64", "amd64")
PYODIDE = "PYODIDE" in os.environ


def spawn(self, cmd, **kwargs) -> None: # type: ignore[no-untyped-def]
if PYODIDE:
new_cmd = list(cmd)
for argument in reversed(new_cmd):
if not str(argument).endswith(".c"):
continue
if "base64/arch/" in str(argument):
new_cmd.extend(["-msimd128"])
else:
compiler_type: str = self.compiler_type
extra_options = EXTRA_FLAGS_PER_COMPILER_TYPE_PER_PATH_COMPONENT[compiler_type]
new_cmd = list(cmd)
if X86_64 and extra_options is not None:
# filenames are closer to the end of command line
for argument in reversed(new_cmd):
# Check if the matching argument contains a source filename.
if not str(argument).endswith(".c"):
continue

for path in extra_options.keys():
if path in str(argument):
if compiler_type == "bcpp":
compiler = new_cmd.pop()
# Borland accepts a source file name at the end,
# insert the options before it
new_cmd.extend(extra_options[path])
new_cmd.append(compiler)
else:
new_cmd.extend(extra_options[path])

# path component is found, no need to search any further
break
self.__spawn(new_cmd, **kwargs)


ccompiler.CCompiler.spawn = spawn # type: ignore[method-assign]
63 changes: 2 additions & 61 deletions mypyc/lib-rt/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from __future__ import annotations

import os
import platform
import subprocess
import sys
from distutils import ccompiler, sysconfig
from typing import Any

import build_setup # noqa: F401
from setuptools import Extension, setup
from setuptools.command.build_ext import build_ext

Expand All @@ -25,63 +25,6 @@
"pythonsupport.c",
]

EXTRA_FLAGS_PER_COMPILER_TYPE_PER_PATH_COMPONENT = {
"unix": {
"base64/arch/ssse3": ["-mssse3"],
"base64/arch/sse41": ["-msse4.1"],
"base64/arch/sse42": ["-msse4.2"],
"base64/arch/avx2": ["-mavx2"],
"base64/arch/avx": ["-mavx"],
},
"msvc": {
"base64/arch/sse42": ["/arch:SSE4.2"],
"base64/arch/avx2": ["/arch:AVX2"],
"base64/arch/avx": ["/arch:AVX"],
},
}

ccompiler.CCompiler.__spawn = ccompiler.CCompiler.spawn # type: ignore[attr-defined]
X86_64 = platform.machine() in ("x86_64", "AMD64", "amd64")
PYODIDE = "PYODIDE" in os.environ


def spawn(self, cmd, **kwargs) -> None: # type: ignore[no-untyped-def]
if PYODIDE:
new_cmd = list(cmd)
for argument in reversed(new_cmd):
if not str(argument).endswith(".c"):
continue
if "base64/arch/" in str(argument):
new_cmd.extend(["-msimd128"])
else:
compiler_type: str = self.compiler_type
extra_options = EXTRA_FLAGS_PER_COMPILER_TYPE_PER_PATH_COMPONENT[compiler_type]
new_cmd = list(cmd)
if X86_64 and extra_options is not None:
# filenames are closer to the end of command line
for argument in reversed(new_cmd):
# Check if the matching argument contains a source filename.
if not str(argument).endswith(".c"):
continue

for path in extra_options.keys():
if path in str(argument):
if compiler_type == "bcpp":
compiler = new_cmd.pop()
# Borland accepts a source file name at the end,
# insert the options before it
new_cmd.extend(extra_options[path])
new_cmd.append(compiler)
else:
new_cmd.extend(extra_options[path])

# path component is found, no need to search any further
break
self.__spawn(new_cmd, **kwargs)


ccompiler.CCompiler.spawn = spawn # type: ignore[method-assign]


class BuildExtGtest(build_ext):
def get_library_names(self) -> list[str]:
Expand Down Expand Up @@ -130,13 +73,11 @@ def run(self) -> None:
cmdclass={"build_ext": BuildExtGtest},
)
else:
# TODO: we need a way to share our preferred C flags and get_extension() logic with
# mypyc/build.py without code duplication.
compiler = ccompiler.new_compiler()
sysconfig.customize_compiler(compiler)
cflags: list[str] = []
if compiler.compiler_type == "unix": # type: ignore[attr-defined]
cflags += ["-O3"]
cflags += ["-O3", "-Wno-unused-function"]
elif compiler.compiler_type == "msvc": # type: ignore[attr-defined]
cflags += ["/O2"]

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def run(self) -> None:
) + (
# Don't want to grab this accidentally
os.path.join("mypyc", "lib-rt", "setup.py"),
os.path.join("mypyc", "lib-rt", "build_setup.py"),
# Uses __file__ at top level https://github.com/mypyc/mypyc/issues/700
os.path.join("mypyc", "__main__.py"),
os.path.join("mypyc", "build_setup.py"), # for monkeypatching
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ commands =
python runtests.py self
python -m mypy --config-file mypy_self_check.ini misc --exclude misc/sync-typeshed.py
python -m mypy --config-file mypy_self_check.ini test-data/unit/plugins
python -m mypy mypyc/lib-rt