Skip to content

Commit 9de9678

Browse files
authored
Merge pull request #3538 from jepler/parallel-qstrlast
build: parallelize the qstr build steps
2 parents 1eb1434 + 8ddbebd commit 9de9678

File tree

3 files changed

+75
-8
lines changed

3 files changed

+75
-8
lines changed

ports/esp32s2/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ menuconfig: $(BUILD)/esp-idf/config
269269
$(Q)grep -Fvxf $(DEBUG_SDKCONFIG) -f $(FLASH_SDKCONFIG) $(BUILD)/sdkconfig.diff > boards/$(BOARD)/sdkconfig
270270

271271
# qstr builds include headers so we need to make sure they are up to date
272-
$(HEADER_BUILD)/qstr.i.last: | $(BUILD)/esp-idf/config/sdkconfig.h
272+
$(HEADER_BUILD)/qstr.split: | $(BUILD)/esp-idf/config/sdkconfig.h
273273

274274
ESP_IDF_COMPONENTS_LINK = freertos log hal esp_system esp_adc_cal esp32s2 bootloader_support pthread esp_timer vfs spi_flash app_update esp_common esp32s2 heap newlib driver xtensa soc esp_ringbuf esp_wifi esp_event wpa_supplicant mbedtls efuse nvs_flash esp_netif lwip esp_rom esp-tls
275275

py/genlast.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
import re
5+
import os
6+
import itertools
7+
from concurrent.futures import ProcessPoolExecutor
8+
import multiprocessing
9+
import threading
10+
import subprocess
11+
12+
from makeqstrdefs import qstr_unescape, QSTRING_BLACK_LIST
13+
14+
re_line = re.compile(r"#[line]*\s(\d+)\s\"([^\"]+)\"", re.DOTALL)
15+
re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+', re.DOTALL)
16+
re_translate = re.compile(r'translate\(\"((?:(?=(\\?))\2.)*?)\"\)', re.DOTALL)
17+
18+
def write_out(fname, output_dir, output):
19+
if output:
20+
for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]:
21+
fname = fname.replace(m, r)
22+
with open(output_dir + "/" + fname + ".qstr", "w") as f:
23+
f.write("\n".join(output) + "\n")
24+
25+
def process_file(fname, output_dir, content):
26+
content = content.decode('utf-8', errors='ignore')
27+
output = []
28+
for match in re_qstr.findall(content):
29+
name = match.replace('MP_QSTR_', '')
30+
if name not in QSTRING_BLACK_LIST:
31+
output.append('Q(' + qstr_unescape(name) + ')')
32+
for match in re_translate.findall(content):
33+
output.append('TRANSLATE("' + match[0] + '")')
34+
35+
write_out(fname, output_dir, output)
36+
37+
38+
def checkoutput1(args):
39+
info = subprocess.run(args, check=True, stdout=subprocess.PIPE, input='')
40+
return info.stdout
41+
42+
def preprocess(command, output_dir, fn):
43+
try:
44+
output = checkoutput1(command + [fn])
45+
process_file(fn, output_dir, output)
46+
except Exception as e:
47+
print(e, file=sys.stderr)
48+
49+
def maybe_preprocess(command, output_dir, fn):
50+
if subprocess.call(["grep", "-lqE", "(MP_QSTR|translate)", fn]) == 0:
51+
preprocess(command, output_dir, fn)
52+
53+
if __name__ == '__main__':
54+
55+
56+
idx1 = sys.argv.index('--')
57+
idx2 = sys.argv.index('--', idx1+1)
58+
output_dir = sys.argv[1]
59+
check = sys.argv[2:idx1]
60+
always = sys.argv[idx1+1:idx2]
61+
command = sys.argv[idx2+1:]
62+
63+
if not os.path.isdir(output_dir):
64+
os.makedirs(output_dir)
65+
66+
# Mac and Windows use 'spawn'. Uncomment this during testing to catch spawn-specific problems on Linux.
67+
#multiprocessing.set_start_method("spawn")
68+
executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count() + 1)
69+
executor.map(maybe_preprocess, itertools.repeat(command), itertools.repeat(output_dir), check)
70+
executor.map(preprocess, itertools.repeat(command), itertools.repeat(output_dir), always)
71+
executor.shutdown()

py/mkrules.mk

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,14 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.enum.h $(HEADER_BUILD)/mpversion.h
7676
# - if anything in QSTR_GLOBAL_DEPENDENCIES is newer, then process all source files ($^)
7777
# - else, if list of newer prerequisites ($?) is not empty, then process just these ($?)
7878
# - else, process all source files ($^) [this covers "make -B" which can set $? to empty]
79-
$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(SRC_QSTR_PREPROCESSOR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h
79+
$(HEADER_BUILD)/qstr.split: $(SRC_QSTR) $(SRC_QSTR_PREPROCESSOR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h $(PY_SRC)/genlast.py
8080
$(STEPECHO) "GEN $@"
81-
$(Q)grep -lE "(MP_QSTR|translate)" $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) | xargs $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(SRC_QSTR_PREPROCESSOR) >$(HEADER_BUILD)/qstr.i.last;
82-
83-
$(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(PY_SRC)/makeqstrdefs.py
84-
$(STEPECHO) "GEN $@"
85-
$(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py split $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)
81+
$(Q)$(PYTHON3) $(PY_SRC)/genlast.py $(HEADER_BUILD)/qstr $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) -- $(SRC_QSTR_PREPROCESSOR) -- $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS)
8682
$(Q)touch $@
8783

8884
$(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split $(PY_SRC)/makeqstrdefs.py
8985
$(STEPECHO) "GEN $@"
90-
$(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py cat $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)
86+
$(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py cat - $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED)
9187

9288
# $(sort $(var)) removes duplicates
9389
#

0 commit comments

Comments
 (0)