Source code for batools.toplevelmakefile

# Released under the MIT License. See LICENSE for details.
#
"""Updates top level Makefile based on project elements present."""

from __future__ import annotations

import os
from typing import TYPE_CHECKING
import subprocess

if TYPE_CHECKING:
    pass


[docs] def generate_top_level_makefile(projroot: str, existing_data: str) -> str: """Main script entry point.""" from efrotools.project import getprojectconfig from pathlib import Path public = getprojectconfig(Path(projroot))['public'] assert isinstance(public, bool) original = existing_data # NOTE: no longer doing this; our dummy module generation stuff is # now a nice static lazybuild target. Can remove this whole file # soon if no other uses for it come up. if bool(False): lines = original.splitlines() auto_start = lines.index('# __AUTOGENERATED_DUMMY_MODULES_BEGIN__') auto_end = lines.index('# __AUTOGENERATED_DUMMY_MODULES_END__') our_lines = [ _get_dummy_module_target(projroot), ] filtered = lines[: auto_start + 1] + our_lines + lines[auto_end:] out = '\n'.join(filtered) + '\n' else: out = original return out
def _get_dummy_module_target(projroot: str) -> str: lines = ( subprocess.run( [ 'find', os.path.join(projroot, 'src/ballistica'), '-name', 'python_*', ], check=True, capture_output=True, ) .stdout.decode() .splitlines() ) targets: list[str] = [] for line in lines: fname = os.path.split(line)[1] if ( fname.startswith('python_class_') or fname.startswith('python_methods_') ) and (fname.endswith('.cc')): assert ' ' not in line assert line.startswith(projroot + '/') targets.append(line.removeprefix(projroot + '/')) # Keep our results deterministic. targets.sort() # Also require a built binary and compiled scripts for it to use. # UPDATE - scratch that. Now just trying to make it clear that # dummy-modules should not be generated as part of regular dependency # setups but rather in a dedicated pass. # targets.append('assets-cmake-scripts') # targets.append('cmake-binary') # Let's just use a single file for dependency tracking and regenerate # all dummy modules when it is dirty. There's basically no speed difference # regenerating all dummy-modules vs a single one so this keeps things # simple. It also lets us blow away any orphaned modules. dmstatepath = 'build/dummymodules/.dummy_modules_state' dmstatedir = os.path.dirname(dmstatepath) out = ( '\n# Update dummy Python modules when source files contributing to' ' them change.\n' f'{dmstatepath}: \\\n' ) # assert targets out += ' \\\n'.join(f' {target}' for target in targets) assert ' ' not in dmstatedir out += ( '\n' f'\t@tools/pcommand with_build_lock gen_dummy_modules_lock \\\n' f' rm -rf {dmstatedir} \\&\\& mkdir -p {dmstatedir} \\\n' ' \\&\\& ./tools/pcommand gen_dummy_modules \\\n' f' \\&\\& touch {dmstatepath}' ) return out