Fix `qmk find` failure due to circular imports (#22523)
There was an import cycle in the Python modules: - `qmk.build_targets` imported `qmk.cli.generate.compilation_database`; - importing `qmk.cli.generate.compilation_database` requires initializing `qmk.cli` first; - the initialization of `qmk.cli` imported the modules for all CLI commands; - `qmk.cli.compile` imported `qmk.build_targets`. This cycle did not matter in most cases, because `qmk.cli` was imported first, and in that case importing `qmk.cli.generate.compilation_database` did not trigger the initialization of `qmk.cli` again. However, there was one corner case when `qmk.bulld_targets` was getting imported first: - The `qmk find` command uses the `multiprocessing` module. - The `multiprocessing` module uses the `spawn` start method on macOS and Windows. - When the `spawn` method is used, the child processes initialize without any Python modules loaded, and the required modules are loaded on demand by the `pickle` module when receiving the serialized objects from the main process. The result was that the `qmk find` command did not work properly on macOS (and probably Windows too); it reported exceptions like this: ImportError: cannot import name 'KeyboardKeymapBuildTarget' from partially initialized module 'qmk.build_targets' (most likely due to a circular import) Moving the offending `qmk.cli.generate.compilation_database` import into the method which actually uses it fixes the problem.master
parent
68722d35a3
commit
7e27d72cbc
|
@ -10,7 +10,6 @@ from qmk.constants import QMK_FIRMWARE, INTERMEDIATE_OUTPUT_PREFIX
|
|||
from qmk.commands import find_make, get_make_parallel_args, parse_configurator_json
|
||||
from qmk.keyboard import keyboard_folder
|
||||
from qmk.info import keymap_json
|
||||
from qmk.cli.generate.compilation_database import write_compilation_database
|
||||
|
||||
|
||||
class BuildTarget:
|
||||
|
@ -105,6 +104,7 @@ class BuildTarget:
|
|||
def generate_compilation_database(self, build_target: str = None, skip_clean: bool = False, **env_vars) -> None:
|
||||
self.prepare_build(build_target=build_target, **env_vars)
|
||||
command = self.compile_command(build_target=build_target, dry_run=True, **env_vars)
|
||||
from qmk.cli.generate.compilation_database import write_compilation_database # Lazy load due to circular references
|
||||
write_compilation_database(command=command, output_path=QMK_FIRMWARE / 'compile_commands.json', skip_clean=skip_clean, **env_vars)
|
||||
|
||||
def compile(self, build_target: str = None, dry_run: bool = False, **env_vars) -> None:
|
||||
|
|
Loading…
Reference in New Issue