From 4c04b1c12c646904d50a580ff4864e1b150cfe64 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 23 Apr 2025 10:49:32 +0100 Subject: [PATCH 1/3] [mypyc] Add hidden flag to skip the generation of C files This can be useful when debugging mypyc issues. For example, you can manually add some debug prints into the generated C and rerun mypyc with `--skip-c-gen`. Now mypyc will build the code again, with your manual changes included (this assumes everything else is the same as during the previous run). There are not plans currently to advertise this as an end-user feature. --- mypy/main.py | 5 +++++ mypy/options.py | 3 +++ mypyc/build.py | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mypy/main.py b/mypy/main.py index e5afb05e873b5..4d9cec63bbc19 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -1128,6 +1128,11 @@ def add_invertible_flag( report_group.add_argument( "-a", dest="mypyc_annotation_file", type=str, default=None, help=argparse.SUPPRESS ) + # Hidden mypyc feature: do not write any C files (keep existing ones and assume they exist). + # This can be useful when debugging mypyc bugs. + report_group.add_argument( + "--skip-c-gen", dest="mypyc_skip_c_generation", action="store_true", help=argparse.SUPPRESS + ) other_group = parser.add_argument_group(title="Miscellaneous") other_group.add_argument("--quickstart-file", help=argparse.SUPPRESS) diff --git a/mypy/options.py b/mypy/options.py index 17fea6b0bf292..5d531412cd216 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -408,6 +408,9 @@ def __init__(self) -> None: # Output html file for mypyc -a self.mypyc_annotation_file: str | None = None + # Skip writing C output files, but perform all other steps of a build (allows + # preserving manual tweaks to generated C file) + self.mypyc_skip_c_generation: bool = False def use_lowercase_names(self) -> bool: if self.python_version >= (3, 9): diff --git a/mypyc/build.py b/mypyc/build.py index 1a74d4692d174..3bc38cb4dd90e 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -452,7 +452,8 @@ def mypyc_build( cfilenames = [] for cfile, ctext in cfiles: cfile = os.path.join(compiler_options.target_dir, cfile) - write_file(cfile, ctext) + if not options.mypyc_skip_c_generation: + write_file(cfile, ctext) if os.path.splitext(cfile)[1] == ".c": cfilenames.append(cfile) From fd515618e5422bcb4ba22f834bb94a3706decc0f Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 23 Apr 2025 11:04:42 +0100 Subject: [PATCH 2/3] Add docs --- mypyc/doc/dev-intro.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mypyc/doc/dev-intro.md b/mypyc/doc/dev-intro.md index 5f6c064dac370..5b248214a3ebc 100644 --- a/mypyc/doc/dev-intro.md +++ b/mypyc/doc/dev-intro.md @@ -386,6 +386,25 @@ Test cases can also have a `[out]` section, which specifies the expected contents of stdout the test case should produce. New test cases should prefer assert statements to `[out]` sections. +### Adding Debug Prints and Editing Generated C + +Sometimes it's helpful to add some debug prints or other debugging helpers +to the generated C code. You can run mypyc using `--skip-c-gen` to skip the C +generation step, so all manual changes to C files are preserved. Here is +an example of how to use the workflow: + +* Compile some file you want to debug: `python -m mypyc foo.py`. +* Add debug prints to the generated C in `build/__native.c`. +* Run the same compilation command line again, but add `--skip-c-gen`: + `python -m mypyc --skip-c-gen foo.py`. This will only rebuild the + binaries. +* Run the compiled code, including your changes: `python -c 'import foo'`. + You should now see the output from the debug prints you added. + +This can also be helpful if you want to quickly experiment with different +implementation techniques, without having to first figure out how to +modify mypyc to generate the desired C code. + ### Debugging Segfaults If you experience a segfault, it's recommended to use a debugger that supports From 40805343b182f038d1676537ccaedb73b1acdc50 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 23 Apr 2025 12:08:59 +0100 Subject: [PATCH 3/3] Remove unneeded annotation --- mypy/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/options.py b/mypy/options.py index 5d531412cd216..c086dfc8aea36 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -410,7 +410,7 @@ def __init__(self) -> None: self.mypyc_annotation_file: str | None = None # Skip writing C output files, but perform all other steps of a build (allows # preserving manual tweaks to generated C file) - self.mypyc_skip_c_generation: bool = False + self.mypyc_skip_c_generation = False def use_lowercase_names(self) -> bool: if self.python_version >= (3, 9):