forked from espressif/esp32-arduino-lib-builder
-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathcompile.py
executable file
·163 lines (137 loc) · 6.28 KB
/
compile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import sys
import subprocess
import os
from rich.console import RenderableType
from textual import on, work
from textual.app import ComposeResult
from textual.binding import Binding
from textual.events import ScreenResume
from textual.containers import Container
from textual.screen import Screen
from textual.widgets import Header, Static, RichLog, Button, Footer
class CompileScreen(Screen):
# Compile screen
# Set the key bindings
BINDINGS = [
Binding("escape", "back", "Back")
]
# Child process running the libraries compilation
child_process = None
log_widget: RichLog
button_widget: Button
def action_back(self) -> None:
self.workers.cancel_all()
if self.child_process:
# Terminate the child process if it is running
print("Terminating child process")
self.child_process.terminate()
try:
self.child_process.stdout.close()
self.child_process.stderr.close()
except:
pass
self.child_process.wait()
self.dismiss()
def print_output(self, renderable: RenderableType, style=None) -> None:
# Print output to the RichLog widget
if style is None:
self.log_widget.write(renderable)
else:
# Check the available styles at https://rich.readthedocs.io/en/stable/style.html
self.log_widget.write("[" + str(style) + "]" + renderable)
def print_error(self, error: str) -> None:
# Print error to the RichLog widget
self.log_widget.write("[b bright_red]" + error)
self.button_widget.add_class("-error")
#print("Error: " + error) # For debugging
def print_success(self, message: str) -> None:
# Print success message to the RichLog widget
self.log_widget.write("[b bright_green]" + message)
self.button_widget.add_class("-success")
#print("Success: " + message) # For debugging
def print_info(self, message: str) -> None:
# Print info message to the RichLog widget
self.log_widget.write("[b bright_cyan]" + message)
#print("Info: " + message) # For debugging
@work(name="compliation_worker", group="compilation", exclusive=True, thread=True)
def compile_libs(self) -> None:
# Compile the libraries
print("Starting compilation process")
label = self.query_one("#compile-title", Static)
self.child_process = None
if self.app.setting_target == ",".join(self.app.supported_targets):
target = "all targets"
else:
target = self.app.setting_target.replace(",", ", ").upper()
label.update("Compiling for " + target)
self.print_info("======== Compiling for " + target + " ========")
command = ["./build.sh", "-t", self.app.setting_target]
#command.append("--help") # For testing output without compiling
if self.app.setting_enable_copy:
if os.path.isdir(self.app.setting_arduino_path):
command.extend(["-c", self.app.setting_arduino_path])
else:
self.print_error("Invalid path to Arduino core: " + self.app.setting_arduino_path)
label.update("Invalid path to Arduino core")
return
if self.app.setting_arduino_branch:
command.extend(["-A", self.app.setting_arduino_branch])
if self.app.setting_idf_branch:
command.extend(["-I", self.app.setting_idf_branch])
if self.app.setting_idf_commit:
command.extend(["-i", self.app.setting_idf_commit])
self.print_info("Running: " + " ".join(command) + "\n")
self.child_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
try:
for output in self.child_process.stdout:
if output == '' and self.child_process.poll() is not None:
break
if output:
self.print_output(output.strip()) # Update RichLog widget with subprocess output
self.child_process.stdout.close()
except Exception as e:
print("Error reading child process output: " + str(e))
print("Process might have terminated")
if not self.child_process:
self.print_error("Compilation failed for " + target + "Child process failed to start")
label.update("Compilation failed for " + target + "Child process failed to start")
return
else:
self.child_process.wait()
if self.child_process.returncode != 0:
self.print_error("Compilation failed for " + target + ". Return code: " + str(self.child_process.returncode))
self.print_error("Errors:")
try:
for error in self.child_process.stderr:
if error:
self.print_error(error.strip())
self.child_process.stderr.close()
except Exception as e:
print("Error reading child process errors: " + str(e))
label.update("Compilation failed for " + target)
else:
self.print_success("Compilation successful for " + target)
label.update("Compilation successful for " + target)
def on_button_pressed(self, event: Button.Pressed) -> None:
# Event handler called when a button is pressed
self.action_back()
@on(ScreenResume)
def on_resume(self) -> None:
# Event handler called every time the screen is activated
print("Compile screen resumed. Clearing logs and starting compilation process")
self.button_widget.remove_class("-error")
self.button_widget.remove_class("-success")
self.log_widget.clear()
self.log_widget.focus()
self.compile_libs()
def compose(self) -> ComposeResult:
# Compose the compilation screen
yield Header()
with Container(id="compile-log-container"):
self.log_widget = RichLog(markup=True, id="compile-log")
yield self.log_widget
with Container(id="compile-status-container"):
yield Static("Compiling for ...", id="compile-title")
self.button_widget = Button("Back", id="compile-back-button")
yield self.button_widget
yield Footer()