Skip to content

Commit

Permalink
Fix qmk find failure due to circular imports (qmk#22523)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sigprof authored and Lorenzo Castoldi committed Dec 27, 2023
1 parent eae745a commit c8cefb2
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion lib/python/qmk/build_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
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:
Expand Down Expand Up @@ -105,6 +104,7 @@ def compile_command(self, build_target: str = None, dry_run: bool = False, **env
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:
Expand Down

0 comments on commit c8cefb2

Please sign in to comment.