Skip to content

Commit 912f66f

Browse files
committed
Move API tables to separate files
1 parent dfe2fee commit 912f66f

11 files changed

Lines changed: 97 additions & 43 deletions

File tree

mypyc/build.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ def build_using_shared_lib(
357357
deps: list[str],
358358
build_dir: str,
359359
extra_compile_args: list[str],
360+
extra_include_dirs: list[str],
360361
) -> list[Extension]:
361362
"""Produce the list of extension modules when a shared library is needed.
362363
@@ -373,7 +374,7 @@ def build_using_shared_lib(
373374
get_extension()(
374375
shared_lib_name(group_name),
375376
sources=cfiles,
376-
include_dirs=[include_dir(), build_dir],
377+
include_dirs=[include_dir(), build_dir] + extra_include_dirs,
377378
depends=deps,
378379
extra_compile_args=extra_compile_args,
379380
)
@@ -399,7 +400,10 @@ def build_using_shared_lib(
399400

400401

401402
def build_single_module(
402-
sources: list[BuildSource], cfiles: list[str], extra_compile_args: list[str]
403+
sources: list[BuildSource],
404+
cfiles: list[str],
405+
extra_compile_args: list[str],
406+
extra_include_dirs: list[str],
403407
) -> list[Extension]:
404408
"""Produce the list of extension modules for a standalone extension.
405409
@@ -409,7 +413,7 @@ def build_single_module(
409413
get_extension()(
410414
sources[0].module,
411415
sources=cfiles,
412-
include_dirs=[include_dir()],
416+
include_dirs=[include_dir()] + extra_include_dirs,
413417
extra_compile_args=extra_compile_args,
414418
)
415419
]
@@ -513,7 +517,9 @@ def mypyc_build(
513517
*,
514518
separate: bool | list[tuple[list[str], str | None]] = False,
515519
only_compile_paths: Iterable[str] | None = None,
516-
skip_cgen_input: tuple[list[list[tuple[str, str]]], list[str]] | None = None,
520+
skip_cgen_input: (
521+
tuple[list[list[tuple[str, str]]], list[tuple[str, bool, list[str]]]] | None
522+
) = None,
517523
always_use_shared_lib: bool = False,
518524
) -> tuple[emitmodule.Groups, list[tuple[list[str], list[str]]], list[SourceDep]]:
519525
"""Do the front and middle end of mypyc building, producing and writing out C source."""
@@ -547,7 +553,10 @@ def mypyc_build(
547553
write_file(os.path.join(compiler_options.target_dir, "ops.txt"), ops_text)
548554
else:
549555
group_cfiles = skip_cgen_input[0]
550-
source_deps = [SourceDep(d) for d in skip_cgen_input[1]]
556+
source_deps = [
557+
SourceDep(path, has_header=hdr, include_dirs=dirs)
558+
for (path, hdr, dirs) in skip_cgen_input[1]
559+
]
551560

552561
# Write out the generated C and collect the files for each group
553562
# Should this be here??
@@ -664,7 +673,9 @@ def mypycify(
664673
strip_asserts: bool = False,
665674
multi_file: bool = False,
666675
separate: bool | list[tuple[list[str], str | None]] = False,
667-
skip_cgen_input: tuple[list[list[tuple[str, str]]], list[str]] | None = None,
676+
skip_cgen_input: (
677+
tuple[list[list[tuple[str, str]]], list[tuple[str, bool, list[str]]]] | None
678+
) = None,
668679
target_dir: str | None = None,
669680
include_runtime_files: bool | None = None,
670681
strict_dunder_typing: bool = False,
@@ -781,12 +792,15 @@ def mypycify(
781792
# runtime library in. Otherwise it just gets #included to save on
782793
# compiler invocations.
783794
shared_cfilenames = []
795+
include_dirs = set()
784796
if not compiler_options.include_runtime_files:
785797
# Collect all files to copy: runtime files + conditional source files
786798
files_to_copy = list(RUNTIME_C_FILES)
787799
for source_dep in source_deps:
788800
files_to_copy.append(source_dep.path)
789-
files_to_copy.append(source_dep.get_header())
801+
if header := source_dep.get_header():
802+
files_to_copy.append(header)
803+
include_dirs.update(source_dep.include_dirs)
790804

791805
# Copy all files
792806
for name in files_to_copy:
@@ -797,6 +811,7 @@ def mypycify(
797811
shared_cfilenames.append(rt_file)
798812

799813
extensions = []
814+
extra_include_dirs = [os.path.join(include_dir(), dir) for dir in include_dirs]
800815
for (group_sources, lib_name), (cfilenames, deps) in zip(groups, group_cfilenames):
801816
if lib_name:
802817
extensions.extend(
@@ -807,11 +822,14 @@ def mypycify(
807822
deps,
808823
build_dir,
809824
cflags,
825+
extra_include_dirs,
810826
)
811827
)
812828
else:
813829
extensions.extend(
814-
build_single_module(group_sources, cfilenames + shared_cfilenames, cflags)
830+
build_single_module(
831+
group_sources, cfilenames + shared_cfilenames, cflags, extra_include_dirs
832+
)
815833
)
816834

817835
if install_librt:

mypyc/codegen/emitmodule.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,8 @@ def collect_source_dependencies(modules: dict[str, ModuleIR]) -> set[SourceDep]:
443443
for dep in module.dependencies:
444444
if isinstance(dep, SourceDep):
445445
source_deps.add(dep)
446+
else:
447+
source_deps.add(dep.static_data_dep())
446448
return source_deps
447449

448450

@@ -585,6 +587,8 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]:
585587
source_deps = collect_source_dependencies(self.modules)
586588
for source_dep in sorted(source_deps, key=lambda d: d.path):
587589
base_emitter.emit_line(f'#include "{source_dep.path}"')
590+
if self.compiler_options.depends_on_librt_internal:
591+
base_emitter.emit_line('#include <internal/librt_internal_static.c>')
588592
base_emitter.emit_line(f'#include "__native{self.short_group_suffix}.h"')
589593
base_emitter.emit_line(f'#include "__native_internal{self.short_group_suffix}.h"')
590594
emitter = base_emitter
@@ -647,7 +651,8 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]:
647651
# Include headers for conditional source files
648652
source_deps = collect_source_dependencies(self.modules)
649653
for source_dep in sorted(source_deps, key=lambda d: d.path):
650-
ext_declarations.emit_line(f'#include "{source_dep.get_header()}"')
654+
if header := source_dep.get_header():
655+
ext_declarations.emit_line(f'#include "{header}"')
651656

652657
declarations = Emitter(self.context)
653658
declarations.emit_line(f"#ifndef MYPYC_LIBRT_INTERNAL{self.group_suffix}_H")

mypyc/ir/deps.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from typing import Final
24

35

@@ -17,17 +19,29 @@ def __eq__(self, other: object) -> bool:
1719
def __hash__(self) -> int:
1820
return hash(("Capsule", self.name))
1921

22+
def static_data_dep(self) -> SourceDep:
23+
module = self.name.split(".")[-1]
24+
return SourceDep(
25+
f"{module}/librt_{module}_static.c", has_header=False, include_dirs=[module]
26+
)
27+
2028

2129
class SourceDep:
2230
"""Defines a C source file that a primitive may require.
2331
24-
Each source file must also have a corresponding .h file (replace .c with .h)
32+
Each source file may also have a corresponding .h file (replace .c with .h)
2533
that gets implicitly #included if the source is used.
34+
include_dirs are passed to the C compiler when the file is compiled as a
35+
shared library separate from the C extension.
2636
"""
2737

28-
def __init__(self, path: str) -> None:
38+
def __init__(
39+
self, path: str, *, has_header: bool = True, include_dirs: list[str] | None = None
40+
) -> None:
2941
# Relative path from mypyc/lib-rt, e.g. 'bytes_extra_ops.c'
3042
self.path: Final = path
43+
self.has_header: Final = has_header
44+
self.include_dirs: Final = include_dirs or []
3145

3246
def __repr__(self) -> str:
3347
return f"SourceDep(path={self.path!r})"
@@ -38,9 +52,9 @@ def __eq__(self, other: object) -> bool:
3852
def __hash__(self) -> int:
3953
return hash(("SourceDep", self.path))
4054

41-
def get_header(self) -> str:
55+
def get_header(self) -> str | None:
4256
"""Get the header file path by replacing .c with .h"""
43-
return self.path.replace(".c", ".h")
57+
return self.path.replace(".c", ".h") if self.has_header else None
4458

4559

4660
Dependency = Capsule | SourceDep
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "librt_base64.h"
2+
3+
void *LibRTBase64_API[LIBRT_BASE64_API_LEN] = {0};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "librt_internal.h"
2+
3+
void *NativeInternal_API[LIBRT_INTERNAL_API_LEN] = {0};

mypyc/lib-rt/static_data.c

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
#ifndef STATIC_DATA
22
#define STATIC_DATA
33

4-
#include "CPy.h"
54
#include "static_data.h"
6-
#include "base64/librt_base64.h"
7-
#include "internal/librt_internal.h"
8-
#include "strings/librt_strings.h"
9-
#include "time/librt_time.h"
10-
#include "vecs/librt_vecs.h"
115

126
// Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.c
137

@@ -78,23 +72,4 @@ intern_strings(void) {
7872
return 0;
7973
}
8074

81-
#ifdef MYPYC_EXPERIMENTAL
82-
83-
void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0};
84-
void *LibRTTime_API[LIBRT_TIME_API_LEN] = {0};
85-
VecCapsule *VecApi = NULL;
86-
VecI64API VecI64Api = {0};
87-
VecI32API VecI32Api = {0};
88-
VecI16API VecI16Api = {0};
89-
VecU8API VecU8Api = {0};
90-
VecFloatAPI VecFloatApi = {0};
91-
VecBoolAPI VecBoolApi = {0};
92-
VecTAPI VecTApi = {0};
93-
VecNestedAPI VecNestedApi = {0};
94-
95-
#endif // MYPYC_EXPERIMENTAL
96-
97-
void *LibRTBase64_API[LIBRT_BASE64_API_LEN] = {0};
98-
void *NativeInternal_API[LIBRT_INTERNAL_API_LEN] = {0};
99-
10075
#endif
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifdef MYPYC_EXPERIMENTAL
2+
3+
#include "librt_strings.h"
4+
5+
void *LibRTStrings_API[LIBRT_STRINGS_API_LEN] = {0};
6+
7+
#endif // MYPYC_EXPERIMENTAL
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifdef MYPYC_EXPERIMENTAL
2+
3+
#include "librt_time.h"
4+
5+
void *LibRTTime_API[LIBRT_TIME_API_LEN] = {0};
6+
7+
#endif // MYPYC_EXPERIMENTAL
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifdef MYPYC_EXPERIMENTAL
2+
3+
#include "librt_vecs.h"
4+
5+
VecCapsule *VecApi = NULL;
6+
VecI64API VecI64Api = {0};
7+
VecI32API VecI32Api = {0};
8+
VecI16API VecI16Api = {0};
9+
VecU8API VecU8Api = {0};
10+
VecFloatAPI VecFloatApi = {0};
11+
VecBoolAPI VecBoolApi = {0};
12+
VecTAPI VecTApi = {0};
13+
VecNestedAPI VecNestedApi = {0};
14+
15+
#endif // MYPYC_EXPERIMENTAL

mypyc/test/test_cheader.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ def check_name(name: str) -> None:
8080
if op.dependencies:
8181
for dep in op.dependencies:
8282
if isinstance(dep, SourceDep):
83-
header_fnam = os.path.join(base_dir, dep.get_header())
84-
if os.path.isfile(header_fnam):
85-
with open(os.path.join(base_dir, header_fnam)) as f:
86-
header += f.read()
83+
if fname := dep.get_header():
84+
header_fnam = os.path.join(base_dir, fname)
85+
if os.path.isfile(header_fnam):
86+
with open(os.path.join(base_dir, header_fnam)) as f:
87+
header += f.read()
8788

8889
for op in all_ops:
8990
if op.c_function_name is not None:

0 commit comments

Comments
 (0)