Skip to content

Commit

Permalink
[mypyc] Add support for building mypyc code on WASM (#13446)
Browse files Browse the repository at this point in the history
### Description

This PR tweaks two things about how mypyc generates and builds C code to
better support WebAssembly. First, we search `sysconfig` for the size of
`size_t`, which works much better for cross-compiling. Second, newer
versions of clang have `-Wno-unused-but-set-variable` and so it is added
to the default list of arguments (this should probably land regardless
the decision on merging this PR).

## Test Plan

This PR depends on #13445. To test
this PR, you can do the following:

*assuming mypy checkout with both PRs applied, must be on Python
3.10(!)*
```
$ pip install pyodide-build
$ pyodide build --exports pyinit backend-args --global-option=--use-mypyc
```
Note: you will get a warning about using `--global-option`, you can
ignore it for now. I'm trying to find out why `--build-option` isn't
working...

Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
  • Loading branch information
ethanhs and hauntsaninja authored Sep 16, 2022
1 parent 7c14fee commit 11be378
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
27 changes: 18 additions & 9 deletions mypy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ class FancyFormatter:
def __init__(self, f_out: IO[str], f_err: IO[str], show_error_codes: bool) -> None:
self.show_error_codes = show_error_codes
# Check if we are in a human-facing terminal on a supported platform.
if sys.platform not in ("linux", "darwin", "win32"):
if sys.platform not in ("linux", "darwin", "win32", "emscripten"):
self.dummy_term = True
return
force_color = int(os.getenv("MYPY_FORCE_COLOR", "0"))
Expand All @@ -534,6 +534,8 @@ def __init__(self, f_out: IO[str], f_err: IO[str], show_error_codes: bool) -> No
return
if sys.platform == "win32":
self.dummy_term = not self.initialize_win_colors()
elif sys.platform == "emscripten":
self.dummy_term = not self.initialize_vt100_colors()
else:
self.dummy_term = not self.initialize_unix_colors()
if not self.dummy_term:
Expand All @@ -545,6 +547,20 @@ def __init__(self, f_out: IO[str], f_err: IO[str], show_error_codes: bool) -> No
"none": "",
}

def initialize_vt100_colors(self) -> bool:
"""Return True if initialization was successful and we can use colors, False otherwise"""
# Windows and Emscripten can both use ANSI/VT100 escape sequences for color
assert sys.platform in ("win32", "emscripten")
self.BOLD = "\033[1m"
self.UNDER = "\033[4m"
self.BLUE = "\033[94m"
self.GREEN = "\033[92m"
self.RED = "\033[91m"
self.YELLOW = "\033[93m"
self.NORMAL = "\033[0m"
self.DIM = "\033[2m"
return True

def initialize_win_colors(self) -> bool:
"""Return True if initialization was successful and we can use colors, False otherwise"""
# Windows ANSI escape sequences are only supported on Threshold 2 and above.
Expand All @@ -571,14 +587,7 @@ def initialize_win_colors(self) -> bool:
| ENABLE_WRAP_AT_EOL_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING,
)
self.BOLD = "\033[1m"
self.UNDER = "\033[4m"
self.BLUE = "\033[94m"
self.GREEN = "\033[92m"
self.RED = "\033[91m"
self.YELLOW = "\033[93m"
self.NORMAL = "\033[0m"
self.DIM = "\033[2m"
self.initialize_vt100_colors()
return True
return False

Expand Down
4 changes: 1 addition & 3 deletions mypyc/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,8 @@ def mypycify(
"-Wno-unused-variable",
"-Wno-unused-command-line-argument",
"-Wno-unknown-warning-option",
"-Wno-unused-but-set-variable",
]
if "gcc" in compiler.compiler[0] or "gnu-cc" in compiler.compiler[0]:
# This flag is needed for gcc but does not exist on clang.
cflags += ["-Wno-unused-but-set-variable"]
elif compiler.compiler_type == "msvc":
# msvc doesn't have levels, '/O2' is full and '/Od' is disable
if opt_level == "0":
Expand Down
19 changes: 15 additions & 4 deletions mypyc/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import sys
import sysconfig
from typing import Any, Dict
from typing_extensions import Final

Expand Down Expand Up @@ -30,7 +31,16 @@
# Maximal number of subclasses for a class to trigger fast path in isinstance() checks.
FAST_ISINSTANCE_MAX_SUBCLASSES: Final = 2

IS_32_BIT_PLATFORM: Final = sys.maxsize < (1 << 31)
# Size of size_t, if configured.
SIZEOF_SIZE_T_SYSCONFIG: Final = sysconfig.get_config_var("SIZEOF_SIZE_T")

SIZEOF_SIZE_T: Final = (
int(SIZEOF_SIZE_T_SYSCONFIG)
if SIZEOF_SIZE_T_SYSCONFIG is not None
else (sys.maxsize + 1).bit_length() // 8
)

IS_32_BIT_PLATFORM: Final = int(SIZEOF_SIZE_T) == 4

PLATFORM_SIZE = 4 if IS_32_BIT_PLATFORM else 8

Expand All @@ -42,15 +52,16 @@
IS_MIXED_32_64_BIT_BUILD: Final = sys.platform in ["darwin"] and sys.version_info < (3, 6)

# Maximum value for a short tagged integer.
MAX_SHORT_INT: Final = sys.maxsize >> 1
MAX_SHORT_INT: Final = 2 ** (8 * int(SIZEOF_SIZE_T) - 2) - 1

# Minimum value for a short tagged integer.
MIN_SHORT_INT: Final = -(sys.maxsize >> 1) - 1
MIN_SHORT_INT: Final = -(MAX_SHORT_INT) - 1

# Maximum value for a short tagged integer represented as a C integer literal.
#
# Note: Assume that the compiled code uses the same bit width as mypyc, except for
# Python 3.5 on macOS.
MAX_LITERAL_SHORT_INT: Final = sys.maxsize >> 1 if not IS_MIXED_32_64_BIT_BUILD else 2**30 - 1
MAX_LITERAL_SHORT_INT: Final = MAX_SHORT_INT if not IS_MIXED_32_64_BIT_BUILD else 2**30 - 1
MIN_LITERAL_SHORT_INT: Final = -MAX_LITERAL_SHORT_INT - 1

# Decription of the C type used to track the definedness of attributes and
Expand Down

0 comments on commit 11be378

Please sign in to comment.