Skip to content

Commit 64c6c5c

Browse files
authored
[mypyc] Reorganize mypyc.build to pull main logic out of mypycify (#7943)
This cleans things up a bit and makes it easier to build (unstable and unsupported!) alternate build system integrations by separating out most of the details of creating the C from anything setuptools related.
1 parent a5ac374 commit 64c6c5c

File tree

1 file changed

+66
-36
lines changed

1 file changed

+66
-36
lines changed

mypyc/build.py

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,58 @@ def get_header_deps(cfiles: List[Tuple[str, str]]) -> List[str]:
369369
return sorted(headers)
370370

371371

372+
def mypyc_build(
373+
paths: List[str],
374+
compiler_options: CompilerOptions,
375+
*,
376+
separate: Union[bool, List[Tuple[List[str], Optional[str]]]] = False,
377+
only_compile_paths: Optional[Iterable[str]] = None,
378+
skip_cgen_input: Optional[Any] = None,
379+
always_use_shared_lib: bool = False
380+
) -> Tuple[emitmodule.Groups, List[Tuple[List[str], List[str]]]]:
381+
"""Do the front and middle end of mypyc building, producing and writing out C source."""
382+
fscache = FileSystemCache()
383+
mypyc_sources, all_sources, options = get_mypy_config(
384+
paths, only_compile_paths, compiler_options, fscache)
385+
386+
# We generate a shared lib if there are multiple modules or if any
387+
# of the modules are in package. (Because I didn't want to fuss
388+
# around with making the single module code handle packages.)
389+
use_shared_lib = (
390+
len(mypyc_sources) > 1
391+
or any('.' in x.module for x in mypyc_sources)
392+
or always_use_shared_lib
393+
)
394+
395+
groups = construct_groups(mypyc_sources, separate, use_shared_lib)
396+
397+
# We let the test harness just pass in the c file contents instead
398+
# so that it can do a corner-cutting version without full stubs.
399+
if not skip_cgen_input:
400+
group_cfiles, ops_text = generate_c(all_sources, options, groups, fscache,
401+
compiler_options=compiler_options)
402+
# TODO: unique names?
403+
write_file(os.path.join(compiler_options.target_dir, 'ops.txt'), ops_text)
404+
else:
405+
group_cfiles = skip_cgen_input
406+
407+
# Write out the generated C and collect the files for each group
408+
# Should this be here??
409+
group_cfilenames = [] # type: List[Tuple[List[str], List[str]]]
410+
for cfiles in group_cfiles:
411+
cfilenames = []
412+
for cfile, ctext in cfiles:
413+
cfile = os.path.join(compiler_options.target_dir, cfile)
414+
write_file(cfile, ctext)
415+
if os.path.splitext(cfile)[1] == '.c':
416+
cfilenames.append(cfile)
417+
418+
deps = [os.path.join(compiler_options.target_dir, dep) for dep in get_header_deps(cfiles)]
419+
group_cfilenames.append((cfilenames, deps))
420+
421+
return groups, group_cfilenames
422+
423+
372424
def mypycify(
373425
paths: List[str],
374426
*,
@@ -421,7 +473,7 @@ def mypycify(
421473
Defaults to False in multi_file mode, True otherwise.
422474
"""
423475

424-
setup_mypycify_vars()
476+
# Figure out our configuration
425477
compiler_options = CompilerOptions(
426478
strip_asserts=strip_asserts,
427479
multi_file=multi_file,
@@ -431,6 +483,18 @@ def mypycify(
431483
include_runtime_files=include_runtime_files,
432484
)
433485

486+
# Generate all the actual important C code
487+
groups, group_cfilenames = mypyc_build(
488+
paths,
489+
only_compile_paths=only_compile_paths,
490+
compiler_options=compiler_options,
491+
separate=separate,
492+
skip_cgen_input=skip_cgen_input,
493+
)
494+
495+
# Mess around with setuptools and actually get the thing built
496+
setup_mypycify_vars()
497+
434498
# Create a compiler object so we can make decisions based on what
435499
# compiler is being used. typeshed is missing some attribues on the
436500
# compiler object so we give it type Any
@@ -439,39 +503,6 @@ def mypycify(
439503

440504
build_dir = compiler_options.target_dir
441505

442-
fscache = FileSystemCache()
443-
mypyc_sources, all_sources, options = get_mypy_config(
444-
paths, only_compile_paths, compiler_options, fscache)
445-
# We generate a shared lib if there are multiple modules or if any
446-
# of the modules are in package. (Because I didn't want to fuss
447-
# around with making the single module code handle packages.)
448-
use_shared_lib = len(mypyc_sources) > 1 or any('.' in x.module for x in mypyc_sources)
449-
450-
groups = construct_groups(mypyc_sources, separate, use_shared_lib)
451-
452-
# We let the test harness just pass in the c file contents instead
453-
# so that it can do a corner-cutting version without full stubs.
454-
if not skip_cgen_input:
455-
group_cfiles, ops_text = generate_c(all_sources, options, groups, fscache,
456-
compiler_options=compiler_options)
457-
# TODO: unique names?
458-
write_file(os.path.join(build_dir, 'ops.txt'), ops_text)
459-
else:
460-
group_cfiles = skip_cgen_input
461-
462-
# Write out the generated C and collect the files for each group
463-
group_cfilenames = [] # type: List[Tuple[List[str], List[str]]]
464-
for cfiles in group_cfiles:
465-
cfilenames = []
466-
for cfile, ctext in cfiles:
467-
cfile = os.path.join(build_dir, cfile)
468-
write_file(cfile, ctext)
469-
if os.path.splitext(cfile)[1] == '.c':
470-
cfilenames.append(cfile)
471-
472-
deps = [os.path.join(build_dir, dep) for dep in get_header_deps(cfiles)]
473-
group_cfilenames.append((cfilenames, deps))
474-
475506
cflags = [] # type: List[str]
476507
if compiler.compiler_type == 'unix':
477508
cflags += [
@@ -513,8 +544,7 @@ def mypycify(
513544

514545
extensions = []
515546
for (group_sources, lib_name), (cfilenames, deps) in zip(groups, group_cfilenames):
516-
if use_shared_lib:
517-
assert lib_name
547+
if lib_name:
518548
extensions.extend(build_using_shared_lib(
519549
group_sources, lib_name, cfilenames + shared_cfilenames, deps, build_dir, cflags))
520550
else:

0 commit comments

Comments
 (0)