931c7c1c51
This 2-in-1 PR started with the goal of support the Bangle.js 2 smartwatch with *no USB*. * Adds "secure" DFU build support with a committed private key. * Adds 3-bit color support with one dummy bit for the JDI memory display * Allows nrf boards to have a board_background_task() run in RUN_BACKGROUND_TASK. This is needed because the Bangle.js 2 uses the watchdog to reset. * Renamed port_background_task() to port_background_tick() to indicate it runs on tick, not RUN_BACKGROUND_TASK. * Marks serial connected when the display terminal is inited. This means that safe mode messages show up on the display. ACep, 7-color epaper displays also pack 3 bits in 4. So, I added that support as well. * Adds 3-bit ACeP color support for 7-color e-paper displays. (Not watch related but similar due to color depth.) * Allows a refresh sequence instead of a single int command. The 7" ACeP display requires a data byte for refresh. * Adds optional delay after resetting the display. The ACeP displays need this. (Probably to load LUTs from flash.) * Adds a cleaning phase for ACeP displays before the real refresh. For both: * Add dither support to Palette. * Palette no longer converts colors when set. Instead, it caches converted colors at each index. * ColorConverter now caches the last converted color. It should make conversions faster for repeated colors (not dithering.)
134 lines
5.0 KiB
Python
Executable File
134 lines
5.0 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
|
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import os
|
|
import multiprocessing
|
|
import sys
|
|
import subprocess
|
|
import shutil
|
|
import build_board_info as build_info
|
|
import time
|
|
|
|
sys.path.append("../docs")
|
|
from shared_bindings_matrix import get_settings_from_makefile
|
|
|
|
for port in build_info.SUPPORTED_PORTS:
|
|
result = subprocess.run("rm -rf ../ports/{port}/build*".format(port=port), shell=True)
|
|
|
|
PARALLEL = "-j 5"
|
|
if "GITHUB_ACTION" in os.environ:
|
|
PARALLEL = "-j 2"
|
|
|
|
all_boards = build_info.get_board_mapping()
|
|
build_boards = list(all_boards.keys())
|
|
if "BOARDS" in os.environ:
|
|
build_boards = os.environ["BOARDS"].split()
|
|
|
|
sha, version = build_info.get_version_info()
|
|
|
|
languages = build_info.get_languages()
|
|
|
|
all_languages = build_info.get_languages(list_all=True)
|
|
|
|
print("Note: Not building languages", set(all_languages) - set(languages))
|
|
|
|
exit_status = 0
|
|
cores = multiprocessing.cpu_count()
|
|
print("building boards with parallelism {}".format(cores))
|
|
for board in build_boards:
|
|
bin_directory = "../bin/{}/".format(board)
|
|
os.makedirs(bin_directory, exist_ok=True)
|
|
board_info = all_boards[board]
|
|
board_settings = get_settings_from_makefile("../ports/" + board_info["port"], board)
|
|
|
|
for language in languages:
|
|
bin_directory = "../bin/{board}/{language}".format(board=board, language=language)
|
|
os.makedirs(bin_directory, exist_ok=True)
|
|
start_time = time.monotonic()
|
|
|
|
# Normally different language builds are all done based on the same set of compiled sources.
|
|
# But sometimes a particular language needs to be built from scratch, if, for instance,
|
|
# CFLAGS_INLINE_LIMIT is set for a particular language to make it fit.
|
|
clean_build_check_result = subprocess.run(
|
|
"make -C ../ports/{port} TRANSLATION={language} BOARD={board} check-release-needs-clean-build -j {cores} | fgrep 'RELEASE_NEEDS_CLEAN_BUILD = 1'".format(
|
|
port=board_info["port"], language=language, board=board, cores=cores
|
|
),
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
)
|
|
clean_build = clean_build_check_result.returncode == 0
|
|
|
|
build_dir = "build-{board}".format(board=board)
|
|
if clean_build:
|
|
build_dir += "-{language}".format(language=language)
|
|
|
|
extensions = [
|
|
extension.strip()
|
|
for extension in board_settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",")
|
|
]
|
|
|
|
artifacts = [os.path.join(build_dir, "firmware." + extension) for extension in extensions]
|
|
make_result = subprocess.run(
|
|
"make -C ../ports/{port} TRANSLATION={language} BOARD={board} BUILD={build} -j {cores} {artifacts}".format(
|
|
port=board_info["port"],
|
|
language=language,
|
|
board=board,
|
|
build=build_dir,
|
|
cores=cores,
|
|
artifacts=" ".join(artifacts),
|
|
),
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
)
|
|
|
|
build_duration = time.monotonic() - start_time
|
|
success = "\033[32msucceeded\033[0m"
|
|
if make_result.returncode != 0:
|
|
exit_status = make_result.returncode
|
|
success = "\033[31mfailed\033[0m"
|
|
|
|
other_output = ""
|
|
|
|
for extension in extensions:
|
|
temp_filename = "../ports/{port}/{build}/firmware.{extension}".format(
|
|
port=board_info["port"], build=build_dir, extension=extension
|
|
)
|
|
for alias in board_info["aliases"] + [board]:
|
|
bin_directory = "../bin/{alias}/{language}".format(alias=alias, language=language)
|
|
os.makedirs(bin_directory, exist_ok=True)
|
|
final_filename = (
|
|
"adafruit-circuitpython-{alias}-{language}-{version}.{extension}".format(
|
|
alias=alias, language=language, version=version, extension=extension
|
|
)
|
|
)
|
|
final_filename = os.path.join(bin_directory, final_filename)
|
|
try:
|
|
shutil.copyfile(temp_filename, final_filename)
|
|
except FileNotFoundError:
|
|
other_output = "Cannot find file {}".format(temp_filename)
|
|
if exit_status == 0:
|
|
exit_status = 1
|
|
|
|
print(
|
|
"Build {board} for {language}{clean_build} took {build_duration:.2f}s and {success}".format(
|
|
board=board,
|
|
language=language,
|
|
clean_build=(" (clean_build)" if clean_build else ""),
|
|
build_duration=build_duration,
|
|
success=success,
|
|
)
|
|
)
|
|
|
|
print(make_result.stdout.decode("utf-8"))
|
|
print(other_output)
|
|
|
|
# Flush so we will see something before 10 minutes has passed.
|
|
print(flush=True)
|
|
|
|
sys.exit(exit_status)
|