mirror of
https://github.com/qmk/qmk_firmware.git
synced 2024-12-05 01:15:19 +00:00
Download relevant toolchain.
This commit is contained in:
parent
3ffe8d917a
commit
33f5e67408
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@
|
|||||||
*.la
|
*.la
|
||||||
*.stackdump
|
*.stackdump
|
||||||
*.sym
|
*.sym
|
||||||
|
qmk_toolchains*
|
||||||
|
|
||||||
# QMK-specific
|
# QMK-specific
|
||||||
api_data/v1
|
api_data/v1
|
||||||
|
@ -82,6 +82,7 @@ subcommands = [
|
|||||||
'qmk.cli.painter',
|
'qmk.cli.painter',
|
||||||
'qmk.cli.pytest',
|
'qmk.cli.pytest',
|
||||||
'qmk.cli.test.c',
|
'qmk.cli.test.c',
|
||||||
|
'qmk.cli.toolchain.commands',
|
||||||
'qmk.cli.userspace.add',
|
'qmk.cli.userspace.add',
|
||||||
'qmk.cli.userspace.compile',
|
'qmk.cli.userspace.compile',
|
||||||
'qmk.cli.userspace.doctor',
|
'qmk.cli.userspace.doctor',
|
||||||
@ -258,3 +259,11 @@ for subcommand in subcommands:
|
|||||||
_eprint(f'Warning: Could not import {subcommand}: {e.__class__.__name__}, {e}')
|
_eprint(f'Warning: Could not import {subcommand}: {e.__class__.__name__}, {e}')
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# Add the QMK toolchains to $PATH
|
||||||
|
try:
|
||||||
|
from qmk.constants import QMK_TOOLCHAINS_PATH # noqa
|
||||||
|
if QMK_TOOLCHAINS_PATH.exists():
|
||||||
|
os.environ['PATH'] = f'{QMK_TOOLCHAINS_PATH}/bin{os.pathsep}{os.environ["PATH"]}'
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
0
lib/python/qmk/cli/toolchain/__init__.py
Normal file
0
lib/python/qmk/cli/toolchain/__init__.py
Normal file
70
lib/python/qmk/cli/toolchain/commands.py
Normal file
70
lib/python/qmk/cli/toolchain/commands.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
"""This script sets up the QMK-provided toolchains.
|
||||||
|
"""
|
||||||
|
import platform
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
from milc import cli
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from qmk.constants import QMK_TOOLCHAINS_PATH, QMK_TOOLCHAINS_TAG
|
||||||
|
from qmk.util import download_with_progress, cached_get
|
||||||
|
|
||||||
|
|
||||||
|
def _os_prefix():
|
||||||
|
os = platform.system().lower()
|
||||||
|
if "linux" in os:
|
||||||
|
return "linux"
|
||||||
|
elif "darwin" in os or "mac" in os or "macos" in os or "osx" in os or "macosx" in os:
|
||||||
|
return "macos"
|
||||||
|
elif "windows" in os or "cygwin" in os or "msys" in os or "win32" in os or "win64" in os or "nt" in os:
|
||||||
|
return "windows"
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def _arch_suffix():
|
||||||
|
arch = platform.machine().lower()
|
||||||
|
if "amd64" in arch or "x86_64" in arch or "x64" in arch or "x86-64" in arch:
|
||||||
|
return "X64"
|
||||||
|
elif "arm64" in arch or "aarch64" in arch:
|
||||||
|
return "ARM64"
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def _os_arch():
|
||||||
|
return f'{_os_prefix()}{_arch_suffix()}'
|
||||||
|
|
||||||
|
|
||||||
|
def _gcc_version_str(gcc_exe):
|
||||||
|
lines = cli.run([gcc_exe, '-v'], check=True, capture_output=True, combined_output=True, stdin=subprocess.DEVNULL).stdout.strip().splitlines()
|
||||||
|
return list(filter(lambda x: x.startswith('gcc version'), lines))[0].strip()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.argument('-t', '--tag', default=QMK_TOOLCHAINS_TAG, help=f'The tag of the QMK-provided toolchains to download. Defaults to `{QMK_TOOLCHAINS_TAG}`.')
|
||||||
|
@cli.subcommand('Set up the QMK-provided toolchains.', hidden=False if cli.config.user.developer else True)
|
||||||
|
def toolchain_setup(cli):
|
||||||
|
"""Set up the QMK-provided toolchains.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Remove the toolchains directory if it exists already
|
||||||
|
if QMK_TOOLCHAINS_PATH.exists():
|
||||||
|
cli.log.info(f'Removing existing toolchains at `{QMK_TOOLCHAINS_PATH}`...')
|
||||||
|
shutil.rmtree(QMK_TOOLCHAINS_PATH)
|
||||||
|
|
||||||
|
url = f'https://api.github.com/repos/qmk/qmk_toolchains/releases/tags/{cli.args.tag}'
|
||||||
|
payload = cached_get(url)
|
||||||
|
if payload.status_code != 200:
|
||||||
|
cli.log.error(f'Failed to fetch toolchain metadata from `{url}`.')
|
||||||
|
return
|
||||||
|
downloadables = filter(lambda x: _os_arch() in x['name'], payload.json()['assets'])
|
||||||
|
for downloadable in downloadables:
|
||||||
|
if not Path(downloadable["name"]).exists():
|
||||||
|
download_with_progress(downloadable['browser_download_url'], downloadable["name"])
|
||||||
|
cli.log.info(f'Extracting `{downloadable["name"]}` to `{QMK_TOOLCHAINS_PATH}`...')
|
||||||
|
QMK_TOOLCHAINS_PATH.mkdir(parents=True, exist_ok=True)
|
||||||
|
cli.run(['tar', 'xf', downloadable["name"], '-C', QMK_TOOLCHAINS_PATH, '--strip-components=1'], capture_output=False, check=True, stdin=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
os.environ['PATH'] = f'{QMK_TOOLCHAINS_PATH}/bin{os.pathsep}{os.environ["PATH"]}'
|
||||||
|
|
||||||
|
for gcc_exe in ['avr-gcc', 'arm-none-eabi-gcc', 'riscv32-unknown-elf-gcc']:
|
||||||
|
cli.log.info(f'{gcc_exe:24s}: {_gcc_version_str(gcc_exe)}')
|
@ -21,6 +21,12 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
|
|||||||
# This is the number of directories under `qmk_firmware/keyboards` that will be traversed. This is currently a limitation of our make system.
|
# This is the number of directories under `qmk_firmware/keyboards` that will be traversed. This is currently a limitation of our make system.
|
||||||
MAX_KEYBOARD_SUBFOLDERS = 5
|
MAX_KEYBOARD_SUBFOLDERS = 5
|
||||||
|
|
||||||
|
# Intended qmk/qmk_toolchains release to deploy
|
||||||
|
QMK_TOOLCHAINS_TAG = 'v14.1.0-4'
|
||||||
|
|
||||||
|
# QMK Toolchains path
|
||||||
|
QMK_TOOLCHAINS_PATH = Path('~/.local/qmk/toolchains').expanduser()
|
||||||
|
|
||||||
# Supported processor types
|
# Supported processor types
|
||||||
CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK64FX512', 'MK66FX1M0', 'RP2040', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32H723', 'STM32H733', 'STM32L412', 'STM32L422', 'STM32L432', 'STM32L433', 'STM32L442', 'STM32L443', 'GD32VF103', 'WB32F3G71', 'WB32FQ95'
|
CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK64FX512', 'MK66FX1M0', 'RP2040', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32H723', 'STM32H733', 'STM32L412', 'STM32L422', 'STM32L432', 'STM32L433', 'STM32L442', 'STM32L443', 'GD32VF103', 'WB32F3G71', 'WB32FQ95'
|
||||||
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
|
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from milc import cli
|
from milc import cli
|
||||||
|
|
||||||
@ -27,6 +28,24 @@ def maybe_exit_config(should_exit: bool = True, should_reraise: bool = False):
|
|||||||
maybe_exit_reraise = should_reraise
|
maybe_exit_reraise = should_reraise
|
||||||
|
|
||||||
|
|
||||||
|
def cached_get(*args, **kwargs):
|
||||||
|
import requests_cache
|
||||||
|
session = requests_cache.CachedSession(Path('~/.local/qmk/qmk_requests.sqlite').expanduser(), expire_after=300, cache_control=True)
|
||||||
|
return session.get(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def download_with_progress(url, filename):
|
||||||
|
import requests
|
||||||
|
import tqdm
|
||||||
|
response = requests.get(url, stream=True)
|
||||||
|
total_size = int(response.headers.get('content-length', 0))
|
||||||
|
with tqdm.tqdm(desc=filename, total=total_size, unit='B', unit_scale=True) as pbar:
|
||||||
|
with open(filename, 'wb') as file:
|
||||||
|
for data in response.iter_content(1024):
|
||||||
|
file.write(data)
|
||||||
|
pbar.update(len(data))
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def parallelize():
|
def parallelize():
|
||||||
"""Returns a function that can be used in place of a map() call.
|
"""Returns a function that can be used in place of a map() call.
|
||||||
|
@ -6,8 +6,11 @@ dotty-dict
|
|||||||
hid
|
hid
|
||||||
hjson
|
hjson
|
||||||
jsonschema>=4
|
jsonschema>=4
|
||||||
milc>=1.4.2
|
milc>=1.8.0
|
||||||
pygments
|
pygments
|
||||||
pyserial
|
pyserial
|
||||||
pyusb
|
pyusb
|
||||||
pillow
|
pillow
|
||||||
|
requests
|
||||||
|
requests-cache
|
||||||
|
tqdm
|
||||||
|
Loading…
Reference in New Issue
Block a user