From a8c8c3ea126255748e12ddf02499213e2312c544 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Tue, 7 Apr 2026 16:54:24 +0200 Subject: [PATCH 1/6] Move strings api table --- mypyc/lib-rt/static_data.c | 7 +++++++ mypyc/lib-rt/strings/librt_strings.h | 2 +- mypyc/test-data/run-multimodule.test | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mypyc/lib-rt/static_data.c b/mypyc/lib-rt/static_data.c index 4416db6cf9ea2..ef3207cfe308e 100644 --- a/mypyc/lib-rt/static_data.c +++ b/mypyc/lib-rt/static_data.c @@ -2,6 +2,7 @@ #define STATIC_DATA #include "static_data.h" +#include "strings/librt_strings.h" // Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.c @@ -72,4 +73,10 @@ intern_strings(void) { return 0; } +#ifdef MYPYC_EXPERIMENTAL + +void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0}; + +#endif // MYPYC_EXPERIMENTAL + #endif diff --git a/mypyc/lib-rt/strings/librt_strings.h b/mypyc/lib-rt/strings/librt_strings.h index 0df2004186556..99d71beab37ce 100644 --- a/mypyc/lib-rt/strings/librt_strings.h +++ b/mypyc/lib-rt/strings/librt_strings.h @@ -30,7 +30,7 @@ import_librt_strings(void) // LIBRT_STRINGS_API_VERSION. #define LIBRT_STRINGS_API_LEN 14 -static void *LibRTStrings_API[LIBRT_STRINGS_API_LEN]; +extern void *LibRTStrings_API[LIBRT_STRINGS_API_LEN]; typedef struct { PyObject_HEAD diff --git a/mypyc/test-data/run-multimodule.test b/mypyc/test-data/run-multimodule.test index db1623fbb6ed0..5986a7e751613 100644 --- a/mypyc/test-data/run-multimodule.test +++ b/mypyc/test-data/run-multimodule.test @@ -1390,3 +1390,23 @@ class Parent: [file driver.py] from native import test test() + +[case testExtraOpsFunction_experimental_librt] +from librt.strings import BytesWriter + +def call_write(b: bytes) -> bytes: + w = BytesWriter() + w.write(b) # calls CPyBytesWriter_Write defined in byteswriter_extra_ops.c + return w.getvalue() + +[file other.py] +from native import call_write + +def test(b: bytes) -> bytes: + return call_write(b) + +[file driver.py] +from other import test + +input = b'x' * 512 +assert test(input) == input From 72d664002322fe47626752dec13b45ae5f714e67 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Tue, 7 Apr 2026 17:12:18 +0200 Subject: [PATCH 2/6] Move other global pointers --- mypyc/lib-rt/base64/librt_base64.h | 2 +- mypyc/lib-rt/internal/librt_internal.h | 2 +- mypyc/lib-rt/static_data.c | 18 ++++++++++++++++++ mypyc/lib-rt/time/librt_time.h | 2 +- mypyc/lib-rt/vecs/librt_vecs.h | 18 +++++++++--------- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/mypyc/lib-rt/base64/librt_base64.h b/mypyc/lib-rt/base64/librt_base64.h index 141f3ce143f69..049191c677289 100644 --- a/mypyc/lib-rt/base64/librt_base64.h +++ b/mypyc/lib-rt/base64/librt_base64.h @@ -7,7 +7,7 @@ #define LIBRT_BASE64_API_VERSION 2 #define LIBRT_BASE64_API_LEN 4 -static void *LibRTBase64_API[LIBRT_BASE64_API_LEN]; +extern void *LibRTBase64_API[LIBRT_BASE64_API_LEN]; #define LibRTBase64_ABIVersion (*(int (*)(void)) LibRTBase64_API[0]) #define LibRTBase64_APIVersion (*(int (*)(void)) LibRTBase64_API[1]) diff --git a/mypyc/lib-rt/internal/librt_internal.h b/mypyc/lib-rt/internal/librt_internal.h index 1b325b20d95bb..cc9b889e1e469 100644 --- a/mypyc/lib-rt/internal/librt_internal.h +++ b/mypyc/lib-rt/internal/librt_internal.h @@ -44,7 +44,7 @@ static int NativeInternal_API_Version(void); #else -static void *NativeInternal_API[LIBRT_INTERNAL_API_LEN]; +extern void *NativeInternal_API[LIBRT_INTERNAL_API_LEN]; #define ReadBuffer_internal (*(PyObject* (*)(PyObject *source)) NativeInternal_API[0]) #define WriteBuffer_internal (*(PyObject* (*)(void)) NativeInternal_API[1]) diff --git a/mypyc/lib-rt/static_data.c b/mypyc/lib-rt/static_data.c index ef3207cfe308e..db8b7ae64b038 100644 --- a/mypyc/lib-rt/static_data.c +++ b/mypyc/lib-rt/static_data.c @@ -1,8 +1,13 @@ #ifndef STATIC_DATA #define STATIC_DATA +#include "CPy.h" #include "static_data.h" +#include "base64/librt_base64.h" +#include "internal/librt_internal.h" #include "strings/librt_strings.h" +#include "time/librt_time.h" +#include "vecs/librt_vecs.h" // Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.c @@ -76,7 +81,20 @@ intern_strings(void) { #ifdef MYPYC_EXPERIMENTAL void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0}; +void *LibRTTime_API[LIBRT_TIME_API_LEN] = {0}; +VecCapsule *VecApi = NULL; +VecI64API VecI64Api = {0}; +VecI32API VecI32Api = {0}; +VecI16API VecI16Api = {0}; +VecU8API VecU8Api = {0}; +VecFloatAPI VecFloatApi = {0}; +VecBoolAPI VecBoolApi = {0}; +VecTAPI VecTApi = {0}; +VecNestedAPI VecNestedApi = {0}; #endif // MYPYC_EXPERIMENTAL +void *LibRTBase64_API[LIBRT_BASE64_API_LEN] = {0}; +void *NativeInternal_API[LIBRT_INTERNAL_API_LEN] = {0}; + #endif diff --git a/mypyc/lib-rt/time/librt_time.h b/mypyc/lib-rt/time/librt_time.h index 72a1f52920bc8..70a7e2f74601c 100644 --- a/mypyc/lib-rt/time/librt_time.h +++ b/mypyc/lib-rt/time/librt_time.h @@ -18,7 +18,7 @@ import_librt_time(void) #define LIBRT_TIME_API_VERSION 1 #define LIBRT_TIME_API_LEN 3 -static void *LibRTTime_API[LIBRT_TIME_API_LEN]; +extern void *LibRTTime_API[LIBRT_TIME_API_LEN]; #define LibRTTime_ABIVersion (*(int (*)(void)) LibRTTime_API[0]) #define LibRTTime_APIVersion (*(int (*)(void)) LibRTTime_API[1]) diff --git a/mypyc/lib-rt/vecs/librt_vecs.h b/mypyc/lib-rt/vecs/librt_vecs.h index e9b93157c7982..f10554d5517d4 100644 --- a/mypyc/lib-rt/vecs/librt_vecs.h +++ b/mypyc/lib-rt/vecs/librt_vecs.h @@ -847,15 +847,15 @@ PyObject *Vec_GenericPopWrapper(Py_ssize_t *len, PyObject **items, PyObject *arg PyObject *Vec_GenericPop(Py_ssize_t *len, PyObject **items, Py_ssize_t index); // Global API pointers initialized by import_librt_vecs() -static VecCapsule *VecApi; -static VecI64API VecI64Api; -static VecI32API VecI32Api; -static VecI16API VecI16Api; -static VecU8API VecU8Api; -static VecFloatAPI VecFloatApi; -static VecBoolAPI VecBoolApi; -static VecTAPI VecTApi; -static VecNestedAPI VecNestedApi; +extern VecCapsule *VecApi; +extern VecI64API VecI64Api; +extern VecI32API VecI32Api; +extern VecI16API VecI16Api; +extern VecU8API VecU8Api; +extern VecFloatAPI VecFloatApi; +extern VecBoolAPI VecBoolApi; +extern VecTAPI VecTApi; +extern VecNestedAPI VecNestedApi; static int import_librt_vecs(void) From f997d91ebfe1a1b93b004f8e06f0830390ccc62b Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 8 Apr 2026 19:06:38 +0200 Subject: [PATCH 3/6] Move API tables to separate files --- mypyc/build.py | 34 ++++++++++++++----- mypyc/codegen/emitmodule.py | 7 +++- mypyc/ir/deps.py | 22 +++++++++--- mypyc/lib-rt/base64/librt_base64_static.c | 3 ++ mypyc/lib-rt/internal/librt_internal_static.c | 3 ++ mypyc/lib-rt/static_data.c | 25 -------------- mypyc/lib-rt/strings/librt_strings_static.c | 7 ++++ mypyc/lib-rt/time/librt_time_static.c | 7 ++++ mypyc/lib-rt/vecs/librt_vecs_static.c | 15 ++++++++ mypyc/test/test_cheader.py | 9 ++--- mypyc/test/test_run.py | 8 ++++- 11 files changed, 97 insertions(+), 43 deletions(-) create mode 100644 mypyc/lib-rt/base64/librt_base64_static.c create mode 100644 mypyc/lib-rt/internal/librt_internal_static.c create mode 100644 mypyc/lib-rt/strings/librt_strings_static.c create mode 100644 mypyc/lib-rt/time/librt_time_static.c create mode 100644 mypyc/lib-rt/vecs/librt_vecs_static.c diff --git a/mypyc/build.py b/mypyc/build.py index 64772c924dc54..bbbbdfa33749c 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -357,6 +357,7 @@ def build_using_shared_lib( deps: list[str], build_dir: str, extra_compile_args: list[str], + extra_include_dirs: list[str], ) -> list[Extension]: """Produce the list of extension modules when a shared library is needed. @@ -373,7 +374,7 @@ def build_using_shared_lib( get_extension()( shared_lib_name(group_name), sources=cfiles, - include_dirs=[include_dir(), build_dir], + include_dirs=[include_dir(), build_dir] + extra_include_dirs, depends=deps, extra_compile_args=extra_compile_args, ) @@ -399,7 +400,10 @@ def build_using_shared_lib( def build_single_module( - sources: list[BuildSource], cfiles: list[str], extra_compile_args: list[str] + sources: list[BuildSource], + cfiles: list[str], + extra_compile_args: list[str], + extra_include_dirs: list[str], ) -> list[Extension]: """Produce the list of extension modules for a standalone extension. @@ -409,7 +413,7 @@ def build_single_module( get_extension()( sources[0].module, sources=cfiles, - include_dirs=[include_dir()], + include_dirs=[include_dir()] + extra_include_dirs, extra_compile_args=extra_compile_args, ) ] @@ -513,7 +517,9 @@ def mypyc_build( *, separate: bool | list[tuple[list[str], str | None]] = False, only_compile_paths: Iterable[str] | None = None, - skip_cgen_input: tuple[list[list[tuple[str, str]]], list[str]] | None = None, + skip_cgen_input: ( + tuple[list[list[tuple[str, str]]], list[tuple[str, bool, list[str]]]] | None + ) = None, always_use_shared_lib: bool = False, ) -> tuple[emitmodule.Groups, list[tuple[list[str], list[str]]], list[SourceDep]]: """Do the front and middle end of mypyc building, producing and writing out C source.""" @@ -547,7 +553,10 @@ def mypyc_build( write_file(os.path.join(compiler_options.target_dir, "ops.txt"), ops_text) else: group_cfiles = skip_cgen_input[0] - source_deps = [SourceDep(d) for d in skip_cgen_input[1]] + source_deps = [ + SourceDep(path, has_header=hdr, include_dirs=dirs) + for (path, hdr, dirs) in skip_cgen_input[1] + ] # Write out the generated C and collect the files for each group # Should this be here?? @@ -664,7 +673,9 @@ def mypycify( strip_asserts: bool = False, multi_file: bool = False, separate: bool | list[tuple[list[str], str | None]] = False, - skip_cgen_input: tuple[list[list[tuple[str, str]]], list[str]] | None = None, + skip_cgen_input: ( + tuple[list[list[tuple[str, str]]], list[tuple[str, bool, list[str]]]] | None + ) = None, target_dir: str | None = None, include_runtime_files: bool | None = None, strict_dunder_typing: bool = False, @@ -781,12 +792,15 @@ def mypycify( # runtime library in. Otherwise it just gets #included to save on # compiler invocations. shared_cfilenames = [] + include_dirs = set() if not compiler_options.include_runtime_files: # Collect all files to copy: runtime files + conditional source files files_to_copy = list(RUNTIME_C_FILES) for source_dep in source_deps: files_to_copy.append(source_dep.path) - files_to_copy.append(source_dep.get_header()) + if header := source_dep.get_header(): + files_to_copy.append(header) + include_dirs.update(source_dep.include_dirs) # Copy all files for name in files_to_copy: @@ -797,6 +811,7 @@ def mypycify( shared_cfilenames.append(rt_file) extensions = [] + extra_include_dirs = [os.path.join(include_dir(), dir) for dir in include_dirs] for (group_sources, lib_name), (cfilenames, deps) in zip(groups, group_cfilenames): if lib_name: extensions.extend( @@ -807,11 +822,14 @@ def mypycify( deps, build_dir, cflags, + extra_include_dirs, ) ) else: extensions.extend( - build_single_module(group_sources, cfilenames + shared_cfilenames, cflags) + build_single_module( + group_sources, cfilenames + shared_cfilenames, cflags, extra_include_dirs + ) ) if install_librt: diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index cb79a25a552d4..8055d0df6584c 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -443,6 +443,8 @@ def collect_source_dependencies(modules: dict[str, ModuleIR]) -> set[SourceDep]: for dep in module.dependencies: if isinstance(dep, SourceDep): source_deps.add(dep) + else: + source_deps.add(dep.static_data_dep()) return source_deps @@ -585,6 +587,8 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]: source_deps = collect_source_dependencies(self.modules) for source_dep in sorted(source_deps, key=lambda d: d.path): base_emitter.emit_line(f'#include "{source_dep.path}"') + if self.compiler_options.depends_on_librt_internal: + base_emitter.emit_line('#include ') base_emitter.emit_line(f'#include "__native{self.short_group_suffix}.h"') base_emitter.emit_line(f'#include "__native_internal{self.short_group_suffix}.h"') emitter = base_emitter @@ -647,7 +651,8 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]: # Include headers for conditional source files source_deps = collect_source_dependencies(self.modules) for source_dep in sorted(source_deps, key=lambda d: d.path): - ext_declarations.emit_line(f'#include "{source_dep.get_header()}"') + if header := source_dep.get_header(): + ext_declarations.emit_line(f'#include "{header}"') declarations = Emitter(self.context) declarations.emit_line(f"#ifndef MYPYC_LIBRT_INTERNAL{self.group_suffix}_H") diff --git a/mypyc/ir/deps.py b/mypyc/ir/deps.py index a342ec152828a..f188df8985cee 100644 --- a/mypyc/ir/deps.py +++ b/mypyc/ir/deps.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Final @@ -17,17 +19,29 @@ def __eq__(self, other: object) -> bool: def __hash__(self) -> int: return hash(("Capsule", self.name)) + def static_data_dep(self) -> SourceDep: + module = self.name.split(".")[-1] + return SourceDep( + f"{module}/librt_{module}_static.c", has_header=False, include_dirs=[module] + ) + class SourceDep: """Defines a C source file that a primitive may require. - Each source file must also have a corresponding .h file (replace .c with .h) + Each source file may also have a corresponding .h file (replace .c with .h) that gets implicitly #included if the source is used. + include_dirs are passed to the C compiler when the file is compiled as a + shared library separate from the C extension. """ - def __init__(self, path: str) -> None: + def __init__( + self, path: str, *, has_header: bool = True, include_dirs: list[str] | None = None + ) -> None: # Relative path from mypyc/lib-rt, e.g. 'bytes_extra_ops.c' self.path: Final = path + self.has_header: Final = has_header + self.include_dirs: Final = include_dirs or [] def __repr__(self) -> str: return f"SourceDep(path={self.path!r})" @@ -38,9 +52,9 @@ def __eq__(self, other: object) -> bool: def __hash__(self) -> int: return hash(("SourceDep", self.path)) - def get_header(self) -> str: + def get_header(self) -> str | None: """Get the header file path by replacing .c with .h""" - return self.path.replace(".c", ".h") + return self.path.replace(".c", ".h") if self.has_header else None Dependency = Capsule | SourceDep diff --git a/mypyc/lib-rt/base64/librt_base64_static.c b/mypyc/lib-rt/base64/librt_base64_static.c new file mode 100644 index 0000000000000..55bc6b4fe1585 --- /dev/null +++ b/mypyc/lib-rt/base64/librt_base64_static.c @@ -0,0 +1,3 @@ +#include "librt_base64.h" + +void *LibRTBase64_API[LIBRT_BASE64_API_LEN] = {0}; diff --git a/mypyc/lib-rt/internal/librt_internal_static.c b/mypyc/lib-rt/internal/librt_internal_static.c new file mode 100644 index 0000000000000..7dff7997f4c89 --- /dev/null +++ b/mypyc/lib-rt/internal/librt_internal_static.c @@ -0,0 +1,3 @@ +#include "librt_internal.h" + +void *NativeInternal_API[LIBRT_INTERNAL_API_LEN] = {0}; diff --git a/mypyc/lib-rt/static_data.c b/mypyc/lib-rt/static_data.c index db8b7ae64b038..4416db6cf9ea2 100644 --- a/mypyc/lib-rt/static_data.c +++ b/mypyc/lib-rt/static_data.c @@ -1,13 +1,7 @@ #ifndef STATIC_DATA #define STATIC_DATA -#include "CPy.h" #include "static_data.h" -#include "base64/librt_base64.h" -#include "internal/librt_internal.h" -#include "strings/librt_strings.h" -#include "time/librt_time.h" -#include "vecs/librt_vecs.h" // Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.c @@ -78,23 +72,4 @@ intern_strings(void) { return 0; } -#ifdef MYPYC_EXPERIMENTAL - -void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0}; -void *LibRTTime_API[LIBRT_TIME_API_LEN] = {0}; -VecCapsule *VecApi = NULL; -VecI64API VecI64Api = {0}; -VecI32API VecI32Api = {0}; -VecI16API VecI16Api = {0}; -VecU8API VecU8Api = {0}; -VecFloatAPI VecFloatApi = {0}; -VecBoolAPI VecBoolApi = {0}; -VecTAPI VecTApi = {0}; -VecNestedAPI VecNestedApi = {0}; - -#endif // MYPYC_EXPERIMENTAL - -void *LibRTBase64_API[LIBRT_BASE64_API_LEN] = {0}; -void *NativeInternal_API[LIBRT_INTERNAL_API_LEN] = {0}; - #endif diff --git a/mypyc/lib-rt/strings/librt_strings_static.c b/mypyc/lib-rt/strings/librt_strings_static.c new file mode 100644 index 0000000000000..8104c94c5c7c3 --- /dev/null +++ b/mypyc/lib-rt/strings/librt_strings_static.c @@ -0,0 +1,7 @@ +#ifdef MYPYC_EXPERIMENTAL + +#include "librt_strings.h" + +void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0}; + +#endif // MYPYC_EXPERIMENTAL diff --git a/mypyc/lib-rt/time/librt_time_static.c b/mypyc/lib-rt/time/librt_time_static.c new file mode 100644 index 0000000000000..8fc457d3ec7d0 --- /dev/null +++ b/mypyc/lib-rt/time/librt_time_static.c @@ -0,0 +1,7 @@ +#ifdef MYPYC_EXPERIMENTAL + +#include "librt_time.h" + +void *LibRTTime_API[LIBRT_TIME_API_LEN] = {0}; + +#endif // MYPYC_EXPERIMENTAL diff --git a/mypyc/lib-rt/vecs/librt_vecs_static.c b/mypyc/lib-rt/vecs/librt_vecs_static.c new file mode 100644 index 0000000000000..218d4d98578e9 --- /dev/null +++ b/mypyc/lib-rt/vecs/librt_vecs_static.c @@ -0,0 +1,15 @@ +#ifdef MYPYC_EXPERIMENTAL + +#include "librt_vecs.h" + +VecCapsule *VecApi = NULL; +VecI64API VecI64Api = {0}; +VecI32API VecI32Api = {0}; +VecI16API VecI16Api = {0}; +VecU8API VecU8Api = {0}; +VecFloatAPI VecFloatApi = {0}; +VecBoolAPI VecBoolApi = {0}; +VecTAPI VecTApi = {0}; +VecNestedAPI VecNestedApi = {0}; + +#endif // MYPYC_EXPERIMENTAL diff --git a/mypyc/test/test_cheader.py b/mypyc/test/test_cheader.py index d955e51e33a69..3c2b80b1b23f6 100644 --- a/mypyc/test/test_cheader.py +++ b/mypyc/test/test_cheader.py @@ -80,10 +80,11 @@ def check_name(name: str) -> None: if op.dependencies: for dep in op.dependencies: if isinstance(dep, SourceDep): - header_fnam = os.path.join(base_dir, dep.get_header()) - if os.path.isfile(header_fnam): - with open(os.path.join(base_dir, header_fnam)) as f: - header += f.read() + if fname := dep.get_header(): + header_fnam = os.path.join(base_dir, fname) + if os.path.isfile(header_fnam): + with open(os.path.join(base_dir, header_fnam)) as f: + header += f.read() for op in all_ops: if op.c_function_name is not None: diff --git a/mypyc/test/test_run.py b/mypyc/test/test_run.py index 8e35f7b1c67a2..bf26c326784e6 100644 --- a/mypyc/test/test_run.py +++ b/mypyc/test/test_run.py @@ -298,7 +298,13 @@ def run_case_step(self, testcase: DataDrivenTestCase, incremental_step: int) -> ir, cfiles, _ = emitmodule.compile_modules_to_c( result, compiler_options=compiler_options, errors=errors, groups=groups ) - deps = sorted(dep.path for dep in collect_source_dependencies(ir)) + deps = sorted( + ( + (dep.path, dep.has_header, dep.include_dirs) + for dep in collect_source_dependencies(ir) + ), + key=lambda tup: tup[0], + ) if errors.num_errors: errors.flush_errors() assert False, "Compile error" From 1059bcfb564ecfd54b3a48b692b6578647236ded Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:10:24 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypyc/codegen/emitmodule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index 8055d0df6584c..e74c10204f4ac 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -588,7 +588,7 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]: for source_dep in sorted(source_deps, key=lambda d: d.path): base_emitter.emit_line(f'#include "{source_dep.path}"') if self.compiler_options.depends_on_librt_internal: - base_emitter.emit_line('#include ') + base_emitter.emit_line("#include ") base_emitter.emit_line(f'#include "__native{self.short_group_suffix}.h"') base_emitter.emit_line(f'#include "__native_internal{self.short_group_suffix}.h"') emitter = base_emitter From b0747db3abc943f83ad2ef070b3732e6115c80f5 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Wed, 8 Apr 2026 19:36:42 +0200 Subject: [PATCH 5/6] Add new files to librt sources --- mypyc/build.py | 20 +++++++++++++++++--- mypyc/lib-rt/internal/librt_internal.h | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mypyc/build.py b/mypyc/build.py index bbbbdfa33749c..a6822b655bf6f 100644 --- a/mypyc/build.py +++ b/mypyc/build.py @@ -53,11 +53,22 @@ class ModDesc(NamedTuple): LIBRT_MODULES = [ - ModDesc("librt.internal", ["internal/librt_internal.c"], [], ["internal"]), - ModDesc("librt.strings", ["strings/librt_strings.c"], [], ["strings"]), + ModDesc( + "librt.internal", + ["internal/librt_internal_static.c", "internal/librt_internal.c"], + [], + ["internal"], + ), + ModDesc( + "librt.strings", + ["strings/librt_strings_static.c", "strings/librt_strings.c"], + [], + ["strings"], + ), ModDesc( "librt.base64", [ + "base64/librt_base64_static.c", "base64/librt_base64.c", "base64/lib.c", "base64/codec_choose.c", @@ -107,6 +118,7 @@ class ModDesc(NamedTuple): ModDesc( "librt.vecs", [ + "vecs/librt_vecs_static.c", "vecs/librt_vecs.c", "vecs/vec_i64.c", "vecs/vec_i32.c", @@ -120,7 +132,9 @@ class ModDesc(NamedTuple): ["vecs/librt_vecs.h", "vecs/vec_template.c"], ["vecs"], ), - ModDesc("librt.time", ["time/librt_time.c"], ["time/librt_time.h"], []), + ModDesc( + "librt.time", ["time/librt_time_static.c", "time/librt_time.c"], ["time/librt_time.h"], [] + ), ] try: diff --git a/mypyc/lib-rt/internal/librt_internal.h b/mypyc/lib-rt/internal/librt_internal.h index cc9b889e1e469..330d1b76452c5 100644 --- a/mypyc/lib-rt/internal/librt_internal.h +++ b/mypyc/lib-rt/internal/librt_internal.h @@ -2,6 +2,7 @@ #define LIBRT_INTERNAL_H #include +#include // ABI version -- only an exact match is compatible. This will only be changed in // very exceptional cases (likely never) due to strict backward compatibility From aa54c7e5bda82adf9ce0753312ec3471c041c021 Mon Sep 17 00:00:00 2001 From: Piotr Sawicki Date: Thu, 9 Apr 2026 13:08:49 +0200 Subject: [PATCH 6/6] Move dependency header includes to internal header --- mypyc/codegen/emitmodule.py | 24 +++++++------ mypyc/test-data/run-multimodule.test | 52 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index e74c10204f4ac..ced8d592e483c 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -638,27 +638,29 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]: ext_declarations.emit_line(f"#define MYPYC_NATIVE{self.group_suffix}_H") ext_declarations.emit_line("#include ") ext_declarations.emit_line("#include ") + + declarations = Emitter(self.context) + declarations.emit_line(f"#ifndef MYPYC_LIBRT_INTERNAL{self.group_suffix}_H") + declarations.emit_line(f"#define MYPYC_LIBRT_INTERNAL{self.group_suffix}_H") + declarations.emit_line("#include ") + declarations.emit_line("#include ") + if self.compiler_options.depends_on_librt_internal: - ext_declarations.emit_line("#include ") + declarations.emit_line("#include ") if any(LIBRT_BASE64 in mod.dependencies for mod in self.modules.values()): - ext_declarations.emit_line("#include ") + declarations.emit_line("#include ") if any(LIBRT_STRINGS in mod.dependencies for mod in self.modules.values()): - ext_declarations.emit_line("#include ") + declarations.emit_line("#include ") if any(LIBRT_TIME in mod.dependencies for mod in self.modules.values()): - ext_declarations.emit_line("#include