Coverage for apio/__main__.py: 89%
35 statements
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
1# This file is part of the Apio project
2# (C) 2016-present FPGAwars
3# Project authors:
4# * Jesús Arroyo (Jesus89) (2016-2019)
5# * Juan Gonzalez (obijuan) (2019-2024)
6# * The Apio Team (2024-present)
7# License: GPLv2
9"""Apio starting point."""
11import sys
12import atexit
13from apio.common.debug_util import is_debug
15# -- IMPORTANT: This module is an entry point for both the Apio
16# -- process and the Scons process (when using under pyinstaller) and
17# -- therefore can depend only on common functionality under
18# -- apio.common.
21debug_enabled = is_debug(1)
24def on_exit(msg):
25 """Prints a debug message on process exit. The msg string is passed
26 from the handler registrations below.
27 """
28 if debug_enabled:
29 print(msg)
32def main():
33 """Apio starting point."""
35 if debug_enabled:
36 print(f"Apio main(): original argv: {sys.argv}")
38 # pylint: disable=import-outside-toplevel
40 # -- Handle the case of the scons subprocess. Because we also use
41 # -- pyinstaller, without standard pip packages, we can't simply invoke
42 # -- the 'scons' binary so we invoke the SCons module from the apio main.
43 # -- See more details at:
44 # -- See https://github.com/orgs/pyinstaller/discussions/9023.
45 # --
46 # -- In this case argv goes through these stages
47 # -- Original: <binary> -m apio --scons ...
48 # -- Under python: <binary> --scons ...
49 # -- Under pyinstaller: <binary> -m apio --scons ...
50 # -- After fixing for scons: <binary> ...
51 # --
52 # -- Notice that the -m apio args are automatically removed by the
53 # -- python interpreter but are preserved by the pyinstaller, hence
54 # -- the two cases.
55 python_scons = sys.argv[1:2] == ["--scons"]
56 pyinstaller_scons = sys.argv[1:4] == ["-m", "apio", "--scons"]
58 if debug_enabled:
59 print(f"Apio main(): {python_scons=}")
60 print(f"Apio main(): {pyinstaller_scons=}")
62 if python_scons or pyinstaller_scons:
64 if debug_enabled: 64 ↛ 65line 64 didn't jump to line 65 because the condition on line 64 was never true
65 print("Apio main(): this is an scons process")
67 # -- Since scons_main() doesn't return, we use this handler to print
68 # -- an exit message for debugging.
69 atexit.register(on_exit, "Apio main(): scons process exit")
71 # -- Import and initialize scons only when running the scons
72 # -- subprocess.
73 from SCons.Script.Main import main as scons_main
74 from apio.common.common_util import maybe_wait_for_remote_debugger
76 # -- If system env var APIO_SCONS_DEBUGGER is defined, regardless of
77 # -- its value, we wait on a remote debugger to be attached, e.g.
78 # -- from Visual Studio Code.
79 # --
80 # -- You can place a breakpoint for example at SconsHandler.start().
81 maybe_wait_for_remote_debugger("APIO_SCONS_DEBUGGER")
83 # -- Drop the scons trigger args
84 if python_scons: 84 ↛ 91line 84 didn't jump to line 91 because the condition on line 84 was always true
85 # -- Case 1: Using a python interpreter which already dropped
86 # -- the ["-m", "apio"]. Dropping just ["--scons"]
87 sys.argv[1:] = sys.argv[2:]
88 else:
89 # -- Case 2: Using pyinstaller which preserved the ["-m", "apio"].
90 # -- Dropping ["-m", "apio", "--scons"]
91 sys.argv[1:] = sys.argv[4:]
93 if debug_enabled: 93 ↛ 94line 93 didn't jump to line 94 because the condition on line 93 was never true
94 print(f"Apio main(): scons fixed argv: {sys.argv}")
96 # -- Invoke the scons main function. It gets the modified argv from sys
97 # -- and doesn't return.
98 scons_main()
100 # -- Handle the case of a normal apio invocation.
101 else:
102 if debug_enabled:
103 print("Apio main(): this is an apio process")
105 # -- Since apio_top_cli() doesn't return, we use this handler to print
106 # -- an exit message for debugging.
107 atexit.register(on_exit, "Apio main(): apio process exit")
109 # -- Import the apio CLI only when running the apio process
110 # -- (as opposed to the scons sub process).
111 from apio.commands.apio import apio_top_cli
113 # -- Due to the Click decorations of apio_top_cli() and the Click
114 # -- magic, this function is not really invoked but Click dispatches
115 # -- it to its subcommands that was selected by the user command line.
116 # -- This function call doesn't return.
117 apio_top_cli()
120if __name__ == "__main__":
121 main()