mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-27 03:21:15 +00:00
Merge d28377237f
into 36c3f4deba
This commit is contained in:
commit
6d8afcba8c
@ -4,7 +4,7 @@ QMK presents itself to the host as a regular HID keyboard device, and as such re
|
|||||||
|
|
||||||
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
|
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
|
||||||
|
|
||||||
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the `qmk_install.sh` script will have already installed the drivers for you.
|
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the QMK CLI installation script will have already installed the drivers for you.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices m
|
|||||||
|
|
||||||
Issues encountered when flashing keyboards on Windows are most often due to having the wrong drivers installed for the bootloader, or none at all.
|
Issues encountered when flashing keyboards on Windows are most often due to having the wrong drivers installed for the bootloader, or none at all.
|
||||||
|
|
||||||
Re-running the QMK installation script (`./util/qmk_install.sh` from the `qmk_firmware` directory in MSYS2 or WSL) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package manually.
|
Re-running the QMK installation script (`curl -fsSL https://install.qmk.fm | sh`) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package manually.
|
||||||
|
|
||||||
If that doesn't work, then you may need to download and run Zadig. See [Bootloader Driver Installation with Zadig](driver_installation_zadig) for more detailed information.
|
If that doesn't work, then you may need to download and run Zadig. See [Bootloader Driver Installation with Zadig](driver_installation_zadig) for more detailed information.
|
||||||
|
|
||||||
|
@ -50,90 +50,64 @@ You will need to install [MSYS2](https://www.msys2.org). Once installed, close a
|
|||||||
Install the QMK CLI by running:
|
Install the QMK CLI by running:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pacman --needed --noconfirm --disable-download-timeout -S git mingw-w64-x86_64-python-qmk
|
curl -fsSL https://install.qmk.fm | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
::::
|
::::
|
||||||
|
|
||||||
==== macOS
|
==== macOS
|
||||||
|
|
||||||
QMK maintains a Homebrew tap and formula which will automatically install the CLI and all necessary dependencies.
|
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
You will need to install Homebrew. Follow the instructions on https://brew.sh.
|
You will need to install Homebrew. Follow the instructions on https://brew.sh.
|
||||||
|
|
||||||
::: tip
|
|
||||||
If you are using an Apple Silicon machine, the installation process will take significantly longer because GitHub actions do not have native runners to build binary packages for the ARM and AVR toolchains.
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
Install the QMK CLI by running:
|
Install the QMK CLI by running:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew install qmk/qmk/qmk
|
curl -fsSL https://install.qmk.fm | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
==== Linux/WSL
|
==== Linux/WSL
|
||||||
|
|
||||||
|
#### Installation
|
||||||
|
|
||||||
|
::: info
|
||||||
|
Many Linux distributions are supported, but not all. Mainstream distributions will have best success -- if possible, choose either Debian or its derivatives (such as Ubuntu, or Mint), CentOS or its derivatives (such as Fedora, or Rocky Linux), and Arch or its derivatives (such as Manjaro, or CachyOS).
|
||||||
|
:::
|
||||||
|
|
||||||
|
Install the QMK CLI by running:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://install.qmk.fm | sh
|
||||||
|
```
|
||||||
|
|
||||||
::: tip
|
::: tip
|
||||||
**Note for WSL users**: By default, the installation process will clone the QMK repository into your WSL home directory, but if you have cloned manually, ensure that it is located inside the WSL instance instead of the Windows filesystem (ie. not in `/mnt`), as accessing it is currently [extremely slow](https://github.com/microsoft/WSL/issues/4197).
|
**Note for WSL users**: By default, the installation process will clone the QMK repository into your WSL home directory, but if you have cloned manually, ensure that it is located inside the WSL instance instead of the Windows filesystem (ie. not in `/mnt`), as accessing it is currently [extremely slow](https://github.com/microsoft/WSL/issues/4197).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
#### Prerequisites
|
::: warning
|
||||||
|
Any QMK packages provided by your distribution's package manager are almost certainly out of date. It is strongly suggested the installation script above is used instead.
|
||||||
You will need to install Git and Python. It's very likely that you already have both, but if not, one of the following commands should install them:
|
:::
|
||||||
|
|
||||||
* Debian / Ubuntu / Devuan: `sudo apt install -y git python3-pip`
|
|
||||||
* Fedora / Red Hat / CentOS: `sudo yum -y install git python3-pip`
|
|
||||||
* Arch / Manjaro: `sudo pacman --needed --noconfirm -S git python-pip libffi`
|
|
||||||
* Void: `sudo xbps-install -y git python3-pip`
|
|
||||||
* Solus: `sudo eopkg -y install git python3`
|
|
||||||
* Sabayon: `sudo equo install dev-vcs/git dev-python/pip`
|
|
||||||
* Gentoo: `sudo emerge dev-vcs/git dev-python/pip`
|
|
||||||
|
|
||||||
#### Installation
|
|
||||||
|
|
||||||
Install the QMK CLI by running:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
python3 -m pip install --user qmk
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, install the QMK CLI as a [uv](https://docs.astral.sh/uv/) managed tool, kept isolated in a virtual environment (requires uv to be installed):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
uv tool install qmk
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Community Packages
|
|
||||||
|
|
||||||
These packages are maintained by community members, so may not be up to date or completely functional. If you encounter problems, please report them to their respective maintainers.
|
|
||||||
|
|
||||||
On Arch-based distros you can install the CLI from the official repositories (NOTE: at the time of writing this package marks some dependencies as optional that should not be):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo pacman -S qmk
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also try the `qmk-git` package from AUR:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yay -S qmk-git
|
|
||||||
```
|
|
||||||
|
|
||||||
==== FreeBSD
|
==== FreeBSD
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
FreeBSD support is provided on a best-effort basis by the community instead of the QMK maintainers. It is strongly suggested that you use either Windows, macOS, or a supported distribution of Linux instead.
|
||||||
|
:::
|
||||||
|
|
||||||
Install the FreeBSD package for QMK CLI by running:
|
Install the FreeBSD package for QMK CLI by running:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkg install -g "py*-qmk"
|
pkg install -g "py*-qmk"
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: remember to follow the instructions printed at the end of installation (use `pkg info -Dg "py*-qmk"` to show them again).
|
::: info NOTE
|
||||||
|
Remember to follow the instructions printed at the end of installation (use `pkg info -Dg "py*-qmk"` to show them again).
|
||||||
|
:::
|
||||||
|
|
||||||
:::::
|
:::::
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
|
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
|
import platformdirs
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
from importlib.util import find_spec
|
from importlib.util import find_spec
|
||||||
@ -12,6 +14,12 @@ from subprocess import run
|
|||||||
from milc import cli, __VERSION__
|
from milc import cli, __VERSION__
|
||||||
from milc.questions import yesno
|
from milc.questions import yesno
|
||||||
|
|
||||||
|
# Ensure the QMK distribution is on the `$PATH` if present.
|
||||||
|
_default_distrib_path = cli.run(['cygpath', '-w', '/opt/qmk']).stdout.strip() if 'windows' in platform.platform().lower() else platformdirs.user_data_dir('qmk') # this must be kept in sync with the default values inside `util/env-bootstrap.sh`!
|
||||||
|
QMK_DISTRIB_DIR = Path(os.environ.get('QMK_DISTRIB_DIR', _default_distrib_path))
|
||||||
|
if QMK_DISTRIB_DIR.exists():
|
||||||
|
os.environ['PATH'] = str(QMK_DISTRIB_DIR / 'bin') + os.pathsep + os.environ['PATH']
|
||||||
|
|
||||||
import_names = {
|
import_names = {
|
||||||
# A mapping of package name to importable name
|
# A mapping of package name to importable name
|
||||||
'pep8-naming': 'pep8ext_naming',
|
'pep8-naming': 'pep8ext_naming',
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""Check for specific programs.
|
"""Check for specific programs.
|
||||||
"""
|
"""
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
from subprocess import DEVNULL, TimeoutExpired
|
from subprocess import DEVNULL, TimeoutExpired
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
@ -18,6 +17,10 @@ class CheckStatus(Enum):
|
|||||||
|
|
||||||
|
|
||||||
ESSENTIAL_BINARIES = {
|
ESSENTIAL_BINARIES = {
|
||||||
|
'make': {},
|
||||||
|
'git': {},
|
||||||
|
'dos2unix': {},
|
||||||
|
'diff': {},
|
||||||
'dfu-programmer': {},
|
'dfu-programmer': {},
|
||||||
'avrdude': {},
|
'avrdude': {},
|
||||||
'dfu-util': {},
|
'dfu-util': {},
|
||||||
@ -30,14 +33,39 @@ ESSENTIAL_BINARIES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _parse_gcc_version(version):
|
def _check_make_version():
|
||||||
m = re.match(r"(\d+)(?:\.(\d+))?(?:\.(\d+))?", version)
|
last_line = ESSENTIAL_BINARIES['make']['output'].split('\n')[0]
|
||||||
|
version_number = last_line.split()[2]
|
||||||
|
cli.log.info('Found make version %s', version_number)
|
||||||
|
|
||||||
return {
|
return CheckStatus.OK
|
||||||
'major': int(m.group(1)),
|
|
||||||
'minor': int(m.group(2)) if m.group(2) else 0,
|
|
||||||
'patch': int(m.group(3)) if m.group(3) else 0,
|
def _check_git_version():
|
||||||
}
|
last_line = ESSENTIAL_BINARIES['git']['output'].split('\n')[0]
|
||||||
|
version_number = last_line.split()[2]
|
||||||
|
cli.log.info('Found git version %s', version_number)
|
||||||
|
|
||||||
|
return CheckStatus.OK
|
||||||
|
|
||||||
|
|
||||||
|
def _check_dos2unix_version():
|
||||||
|
last_line = ESSENTIAL_BINARIES['dos2unix']['output'].split('\n')[0]
|
||||||
|
version_number = last_line.split()[1]
|
||||||
|
cli.log.info('Found dos2unix version %s', version_number)
|
||||||
|
|
||||||
|
return CheckStatus.OK
|
||||||
|
|
||||||
|
|
||||||
|
def _check_diff_version():
|
||||||
|
last_line = ESSENTIAL_BINARIES['diff']['output'].split('\n')[0]
|
||||||
|
if 'Apple diff' in last_line:
|
||||||
|
version_number = last_line
|
||||||
|
else:
|
||||||
|
version_number = last_line.split()[3]
|
||||||
|
cli.log.info('Found diff version %s', version_number)
|
||||||
|
|
||||||
|
return CheckStatus.OK
|
||||||
|
|
||||||
|
|
||||||
def _check_arm_gcc_version():
|
def _check_arm_gcc_version():
|
||||||
@ -148,16 +176,24 @@ def check_binaries():
|
|||||||
"""Iterates through ESSENTIAL_BINARIES and tests them.
|
"""Iterates through ESSENTIAL_BINARIES and tests them.
|
||||||
"""
|
"""
|
||||||
ok = CheckStatus.OK
|
ok = CheckStatus.OK
|
||||||
|
missing_from_path = []
|
||||||
|
|
||||||
for binary in sorted(ESSENTIAL_BINARIES):
|
for binary in sorted(ESSENTIAL_BINARIES):
|
||||||
try:
|
try:
|
||||||
if not is_executable(binary):
|
if not is_in_path(binary):
|
||||||
|
ok = CheckStatus.ERROR
|
||||||
|
missing_from_path.append(binary)
|
||||||
|
elif not is_executable(binary):
|
||||||
ok = CheckStatus.ERROR
|
ok = CheckStatus.ERROR
|
||||||
except TimeoutExpired:
|
except TimeoutExpired:
|
||||||
cli.log.debug('Timeout checking %s', binary)
|
cli.log.debug('Timeout checking %s', binary)
|
||||||
if ok != CheckStatus.ERROR:
|
if ok != CheckStatus.ERROR:
|
||||||
ok = CheckStatus.WARNING
|
ok = CheckStatus.WARNING
|
||||||
|
|
||||||
|
if missing_from_path:
|
||||||
|
location_noun = 'its location' if len(missing_from_path) == 1 else 'their locations'
|
||||||
|
cli.log.error('{fg_red}' + ', '.join(missing_from_path) + f' may need to be installed, or {location_noun} added to your path.')
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
@ -165,6 +201,10 @@ def check_binary_versions():
|
|||||||
"""Check the versions of ESSENTIAL_BINARIES
|
"""Check the versions of ESSENTIAL_BINARIES
|
||||||
"""
|
"""
|
||||||
checks = {
|
checks = {
|
||||||
|
'make': _check_make_version,
|
||||||
|
'git': _check_git_version,
|
||||||
|
'dos2unix': _check_dos2unix_version,
|
||||||
|
'diff': _check_diff_version,
|
||||||
'arm-none-eabi-gcc': _check_arm_gcc_version,
|
'arm-none-eabi-gcc': _check_arm_gcc_version,
|
||||||
'avr-gcc': _check_avr_gcc_version,
|
'avr-gcc': _check_avr_gcc_version,
|
||||||
'avrdude': _check_avrdude_version,
|
'avrdude': _check_avrdude_version,
|
||||||
@ -196,15 +236,18 @@ def check_submodules():
|
|||||||
return CheckStatus.OK
|
return CheckStatus.OK
|
||||||
|
|
||||||
|
|
||||||
def is_executable(command):
|
def is_in_path(command):
|
||||||
"""Returns True if command exists and can be executed.
|
"""Returns True if command is found in the path.
|
||||||
"""
|
"""
|
||||||
# Make sure the command is in the path.
|
if shutil.which(command) is None:
|
||||||
res = shutil.which(command)
|
|
||||||
if res is None:
|
|
||||||
cli.log.error("{fg_red}Can't find %s in your path.", command)
|
cli.log.error("{fg_red}Can't find %s in your path.", command)
|
||||||
return False
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_executable(command):
|
||||||
|
"""Returns True if command can be executed.
|
||||||
|
"""
|
||||||
# Make sure the command can be executed
|
# Make sure the command can be executed
|
||||||
version_arg = ESSENTIAL_BINARIES[command].get('version_arg', '--version')
|
version_arg = ESSENTIAL_BINARIES[command].get('version_arg', '--version')
|
||||||
check = cli.run([command, version_arg], combined_output=True, stdin=DEVNULL, timeout=5)
|
check = cli.run([command, version_arg], combined_output=True, stdin=DEVNULL, timeout=5)
|
||||||
|
@ -16,6 +16,34 @@ from qmk.commands import in_virtualenv
|
|||||||
from qmk.userspace import qmk_userspace_paths, qmk_userspace_validate, UserspaceValidationError
|
from qmk.userspace import qmk_userspace_paths, qmk_userspace_validate, UserspaceValidationError
|
||||||
|
|
||||||
|
|
||||||
|
def distrib_tests():
|
||||||
|
def _parse_distrib_info_file(file):
|
||||||
|
"""Parse the QMK distribution info file
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
vars = {}
|
||||||
|
with open(file, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if '=' in line:
|
||||||
|
key, value = line.split('=', 1)
|
||||||
|
vars[key.strip()] = value.strip()
|
||||||
|
return f'{vars.get("TOOLCHAIN_HOST", "unknown")}:{vars.get("TOOLCHAIN_TARGET", "unknown")}:{vars.get("COMMIT_HASH", "unknown")}'
|
||||||
|
except Exception as e:
|
||||||
|
cli.log.warning('Error reading QMK distribution info file: %s', e)
|
||||||
|
return f'Unknown toolchain info file: {file}'
|
||||||
|
|
||||||
|
try:
|
||||||
|
from qmk.cli import QMK_DISTRIB_DIR
|
||||||
|
if (QMK_DISTRIB_DIR / 'etc').exists():
|
||||||
|
cli.log.info('Found QMK tools distribution directory: {fg_cyan}%s', QMK_DISTRIB_DIR)
|
||||||
|
toolchains = [_parse_distrib_info_file(file) for file in (QMK_DISTRIB_DIR / 'etc').glob('toolchain_release_*')]
|
||||||
|
cli.log.info('Found QMK toolchains: {fg_cyan}%s', ', '.join(toolchains))
|
||||||
|
except ImportError:
|
||||||
|
cli.log.info('QMK tools distribution not found.')
|
||||||
|
|
||||||
|
return CheckStatus.OK
|
||||||
|
|
||||||
|
|
||||||
def os_tests():
|
def os_tests():
|
||||||
"""Determine our OS and run platform specific tests
|
"""Determine our OS and run platform specific tests
|
||||||
"""
|
"""
|
||||||
@ -128,6 +156,7 @@ def doctor(cli):
|
|||||||
cli.log.info('QMK home: {fg_cyan}%s', QMK_FIRMWARE)
|
cli.log.info('QMK home: {fg_cyan}%s', QMK_FIRMWARE)
|
||||||
|
|
||||||
status = os_status = os_tests()
|
status = os_status = os_tests()
|
||||||
|
distrib_tests()
|
||||||
|
|
||||||
userspace_tests(None)
|
userspace_tests(None)
|
||||||
|
|
||||||
|
521
util/env-bootstrap.sh
Executable file
521
util/env-bootstrap.sh
Executable file
@ -0,0 +1,521 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Copyright 2025 Nick Brassel (@tzarc)
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# This script will install the QMK CLI, toolchains, and flashing utilities.
|
||||||
|
################################################################################
|
||||||
|
# Environment variables:
|
||||||
|
# CONFIRM: Skip the pre-install delay. (or: --confirm)
|
||||||
|
# QMK_DISTRIB_DIR: The directory to install the QMK distribution to. (or: --qmk-distrib-dir=...)
|
||||||
|
# UV_INSTALL_DIR: The directory to install `uv` to. (or: --uv-install-dir=...)
|
||||||
|
# UV_TOOL_DIR: The directory to install `uv` tools to. (or: --uv-tool-dir=...)
|
||||||
|
# SKIP_CLEAN: Skip cleaning the distribution directory. (or: --skip-clean)
|
||||||
|
# SKIP_PACKAGE_MANAGER: Skip installing the necessary packages for the package manager. (or: --skip-package-manager)
|
||||||
|
# SKIP_UV: Skip installing `uv`. (or: --skip-uv)
|
||||||
|
# SKIP_QMK_CLI: Skip installing the QMK CLI. (or: --skip-qmk-cli)
|
||||||
|
# SKIP_QMK_TOOLCHAINS: Skip installing the QMK toolchains. (or: --skip-qmk-toolchains)
|
||||||
|
# SKIP_QMK_FLASHUTILS: Skip installing the QMK flashing utilities. (or: --skip-qmk-flashutils)
|
||||||
|
# SKIP_UDEV_RULES: Skip installing the udev rules for Linux. (or: --skip-udev-rules)
|
||||||
|
# SKIP_WINDOWS_DRIVERS: Skip installing the Windows drivers for the flashing utilities. (or: --skip-windows-drivers)
|
||||||
|
#
|
||||||
|
# Arguments above may be negated by prefixing with `--no-` instead (e.g. `--no-skip-clean`).
|
||||||
|
################################################################################
|
||||||
|
# Usage:
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh
|
||||||
|
#
|
||||||
|
# Help:
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh -s -- --help
|
||||||
|
#
|
||||||
|
# An example which skips installing `uv` using environment variables:
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | SKIP_UV=1 sh
|
||||||
|
#
|
||||||
|
# ...or by using command line arguments:
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh -s -- --skip-uv
|
||||||
|
#
|
||||||
|
# Any other configurable items listed above may be specified in the same way.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
{ # this ensures the entire script is downloaded #
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# Work out which `sed` to use
|
||||||
|
command -v gsed >/dev/null 2>&1 && SED=gsed || SED=sed
|
||||||
|
|
||||||
|
script_args() {
|
||||||
|
cat <<__EOT__
|
||||||
|
--help -- Shows this help text
|
||||||
|
--confirm -- Skips the delay before installation
|
||||||
|
--uv-install-dir={path} -- The directory to install \`uv\` into
|
||||||
|
--uv-tool-dir={path} -- The directory to install \`uv\` tools into
|
||||||
|
--qmk-distrib-dir={path} -- The directory to install the QMK distribution into
|
||||||
|
--skip-clean -- Skip cleaning the QMK distribution directory
|
||||||
|
--skip-package-manager -- Skip installing the necessary packages for the package manager
|
||||||
|
--skip-uv -- Skip installing \`uv\`
|
||||||
|
--skip-qmk-cli -- Skip installing the QMK CLI
|
||||||
|
--skip-qmk-toolchains -- Skip installing the QMK toolchains
|
||||||
|
--skip-qmk-flashutils -- Skip installing the QMK flashing utilities
|
||||||
|
--skip-udev-rules -- Skip installing the udev rules for Linux
|
||||||
|
--skip-windows-drivers -- Skip installing the Windows drivers for the flashing utilities
|
||||||
|
__EOT__
|
||||||
|
}
|
||||||
|
|
||||||
|
script_help() {
|
||||||
|
echo "$(basename ${this_script:-qmk-install.sh}) $(script_args | sort | ${SED} -e 's@^\s*@@g' -e 's@\s\+--.*@@g' -e 's@^@[@' -e 's@$@]@' | tr '\n' ' ')"
|
||||||
|
echo
|
||||||
|
echo "Arguments:"
|
||||||
|
script_args
|
||||||
|
echo
|
||||||
|
echo "Switch arguments may be negated by prefixing with '--no-' (e.g. '--no-skip-clean')."
|
||||||
|
}
|
||||||
|
|
||||||
|
script_parse_args() {
|
||||||
|
local N
|
||||||
|
local V
|
||||||
|
while [ ! -z "${1:-}" ]; do
|
||||||
|
case "$1" in
|
||||||
|
--help)
|
||||||
|
script_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--*=*)
|
||||||
|
N=${1%%=*}
|
||||||
|
N=${N##--}
|
||||||
|
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
|
||||||
|
V=${1##*=}
|
||||||
|
export $N="$V"
|
||||||
|
;;
|
||||||
|
--no-*)
|
||||||
|
N=${1##--no-}
|
||||||
|
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
|
||||||
|
unset $N
|
||||||
|
;;
|
||||||
|
--*)
|
||||||
|
N=${1##--}
|
||||||
|
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
|
||||||
|
export $N=true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: '$1'" >&2
|
||||||
|
echo
|
||||||
|
script_help >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
unset N
|
||||||
|
unset V
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
nsudo() {
|
||||||
|
if [ "$(fn_os)" = "windows" ]; then
|
||||||
|
# No need for sudo under QMK MSYS
|
||||||
|
return
|
||||||
|
elif [ $(id -u) -ne 0 ]; then
|
||||||
|
echo "sudo"
|
||||||
|
fi
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
download_url() {
|
||||||
|
local url=$1
|
||||||
|
local filename=${2:-$(basename "$url")}
|
||||||
|
local quiet=''
|
||||||
|
if [ -n "$(command -v curl 2>/dev/null || true)" ]; then
|
||||||
|
[ "$filename" = "-" ] && quiet='-s' || echo "Downloading '$url' => '$filename'" >&2
|
||||||
|
curl -LSf $quiet -o "$filename" "$url"
|
||||||
|
elif [ -n "$(command -v wget 2>/dev/null || true)" ]; then
|
||||||
|
[ "$filename" = "-" ] && quiet='-q' || echo "Downloading '$url' => '$filename'" >&2
|
||||||
|
wget $quiet "-O$filename" "$url"
|
||||||
|
else
|
||||||
|
echo "Please install 'curl' or 'wget' to continue." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_os() {
|
||||||
|
local os_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
|
||||||
|
if [ -z "$os_name" ]; then
|
||||||
|
os_name=$(uname -s | tr 'A-Z' 'a-z')
|
||||||
|
fi
|
||||||
|
case "$os_name" in
|
||||||
|
*darwin* | *macos* | *apple*)
|
||||||
|
echo macos
|
||||||
|
;;
|
||||||
|
*windows* | *mingw* | *w64*)
|
||||||
|
echo windows
|
||||||
|
;;
|
||||||
|
*linux*)
|
||||||
|
echo linux
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo unknown
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_arch() {
|
||||||
|
local arch_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
|
||||||
|
if [ -z "$arch_name" ]; then
|
||||||
|
arch_name=$(uname -m | tr 'A-Z' 'a-z')
|
||||||
|
fi
|
||||||
|
case "$arch_name" in
|
||||||
|
*arm64* | *aarch64*)
|
||||||
|
echo ARM64
|
||||||
|
;;
|
||||||
|
*riscv64*)
|
||||||
|
echo RV64
|
||||||
|
;;
|
||||||
|
*x86_64* | *x64*)
|
||||||
|
echo X64
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo unknown
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
preinstall_delay() {
|
||||||
|
[ -z "${CONFIRM:-}" ] || return 0
|
||||||
|
echo >&2
|
||||||
|
echo "Waiting 10 seconds before proceeding. Press Ctrl+C to cancel installation." >&2
|
||||||
|
sleep 10
|
||||||
|
}
|
||||||
|
|
||||||
|
get_package_manager_deps() {
|
||||||
|
case $(fn_os) in
|
||||||
|
macos) echo "zstd clang-format make hidapi libusb dos2unix git" ;;
|
||||||
|
windows) echo "base-devel: zstd:x toolchain:x clang:x hidapi:x dos2unix: git: unzip:" ;;
|
||||||
|
linux)
|
||||||
|
case $(grep ID /etc/os-release) in
|
||||||
|
*arch* | *manjaro* | *cachyos*) echo "zstd base-devel clang diffutils unzip wget zip hidapi dos2unix git" ;;
|
||||||
|
*debian* | *ubuntu*) echo "zstd build-essential clang-format diffutils unzip wget zip libhidapi-hidraw0 dos2unix git" ;;
|
||||||
|
*fedora*) echo "zstd clang diffutils gcc git unzip wget zip hidapi dos2unix libusb-devel libusb1-devel libusb-compat-0.1-devel libusb0-devel git" ;;
|
||||||
|
*gentoo*) echo "app-arch/zstd app-arch/unzip app-arch/zip net-misc/wget llvm-core/clang sys-apps/hwloc dev-libs/hidapi app-text/dos2unix dev-vcs/git" ;;
|
||||||
|
*slackware*) echo "python3" ;;
|
||||||
|
*solus*) echo "system.devel zstd git wget zip unzip python3 dos2unix git" ;;
|
||||||
|
*void*) echo "zstd git make wget unzip zip python3 dos2unix git" ;;
|
||||||
|
*)
|
||||||
|
echo "Sorry, we don't recognize your distribution. Try using the docker image instead:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo "https://docs.qmk.fm/#/getting_started_docker" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Sorry, we don't recognize your OS. Try using a compatible OS instead:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo "https://docs.qmk.fm/newbs_getting_started#set-up-your-environment" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
print_package_manager_deps_and_delay() {
|
||||||
|
get_package_manager_deps | tr ' ' '\n' | sort | xargs -I'{}' echo " - {}" >&2
|
||||||
|
preinstall_delay || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install_package_manager_deps() {
|
||||||
|
# Install the necessary packages for the package manager
|
||||||
|
case $(fn_os) in
|
||||||
|
macos)
|
||||||
|
if [ -n "$(command -v brew 2>/dev/null || true)" ]; then
|
||||||
|
echo "It will also install the following system packages using 'brew':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
brew update && brew upgrade --formulae
|
||||||
|
brew install $(get_package_manager_deps)
|
||||||
|
else
|
||||||
|
echo "Please install 'brew' to continue. See https://brew.sh/ for more information." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
windows)
|
||||||
|
echo "It will also install the following packages using 'pacman'/'pacboy':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) pacman --needed --noconfirm --disable-download-timeout -S pactoys
|
||||||
|
$(nsudo) pacboy sync --needed --noconfirm --disable-download-timeout $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
linux)
|
||||||
|
case $(grep ID /etc/os-release) in
|
||||||
|
*arch* | *manjaro* | *cachyos*)
|
||||||
|
echo "It will also install the following system packages using 'pacman':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) pacman --needed --noconfirm -S $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*debian* | *ubuntu*)
|
||||||
|
echo "It will also install the following system packages using 'apt':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) apt-get update
|
||||||
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
|
$(nsudo) apt-get --quiet --yes install $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*fedora*)
|
||||||
|
echo "It will also install the following system packages using 'dnf':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) dnf -y install $(get_package_manager_deps) --skip-unavailable
|
||||||
|
;;
|
||||||
|
*gentoo*)
|
||||||
|
echo "It will also the following packages using 'emerge':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) emerge -au --noreplace $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*slackware*)
|
||||||
|
echo "It will also the following packages using 'sboinstall':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) sboinstall $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*solus*)
|
||||||
|
echo "It will also install the following system packages using 'eopkg':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) eopkg -y update-repo
|
||||||
|
$(nsudo) eopkg -y upgrade
|
||||||
|
$(nsudo) eopkg -y install $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*void*)
|
||||||
|
echo "It will also the following packages using 'xbps-install':" >&2
|
||||||
|
print_package_manager_deps_and_delay
|
||||||
|
$(nsudo) xbps-install -y $(get_package_manager_deps)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Sorry, we don't recognize your distribution. Try using the docker image instead:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo "https://docs.qmk.fm/#/getting_started_docker" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
install_uv() {
|
||||||
|
# Install `uv` (or update as necessary)
|
||||||
|
download_url https://astral.sh/uv/install.sh - | TMPDIR="$(windows_ish_path "${TMPDIR:-}")" UV_INSTALL_DIR="$(windows_ish_path "${UV_INSTALL_DIR:-}")" sh
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_paths() {
|
||||||
|
# Set up the paths for any of the locations `uv` expects
|
||||||
|
if [ -n "${XDG_BIN_HOME:-}" ]; then
|
||||||
|
export PATH="$XDG_BIN_HOME:$PATH"
|
||||||
|
fi
|
||||||
|
if [ -n "${XDG_DATA_HOME:-}" ]; then
|
||||||
|
export PATH="$XDG_DATA_HOME/../bin:$PATH"
|
||||||
|
fi
|
||||||
|
[ ! -d "$HOME/.local/bin" ] || export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if [ -n "${UV_INSTALL_DIR:-}" ]; then
|
||||||
|
export PATH="$UV_INSTALL_DIR/bin:$UV_INSTALL_DIR:$PATH" # cater for both "flat" and "hierarchical" installs of `uv`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${UV_TOOL_BIN_DIR:-}" ]; then
|
||||||
|
export PATH="$UV_TOOL_BIN_DIR:$PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_command() {
|
||||||
|
if [ "$(fn_os)" = "windows" ]; then
|
||||||
|
UV_TOOL_DIR="$(windows_ish_path "${UV_TOOL_DIR:-}")" \
|
||||||
|
UV_TOOL_BIN_DIR="$(windows_ish_path "${UV_TOOL_BIN_DIR:-}")" \
|
||||||
|
uv "$@"
|
||||||
|
else
|
||||||
|
uv "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_qmk_cli() {
|
||||||
|
# Install the QMK CLI
|
||||||
|
uv_command tool install --force --with pip --upgrade --python $PYTHON_TARGET_VERSION qmk
|
||||||
|
|
||||||
|
# QMK is installed to...
|
||||||
|
local qmk_tooldir="$(posix_ish_path "$(uv_command tool dir)/qmk")"
|
||||||
|
|
||||||
|
# Activate the environment
|
||||||
|
if [ -e "$qmk_tooldir/bin" ]; then
|
||||||
|
. "$qmk_tooldir/bin/activate"
|
||||||
|
elif [ -e "$qmk_tooldir/Scripts" ]; then
|
||||||
|
. "$qmk_tooldir/Scripts/activate"
|
||||||
|
else
|
||||||
|
echo "Could not find the QMK environment to activate." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install the QMK dependencies
|
||||||
|
uv_command pip install --upgrade -r https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/requirements.txt
|
||||||
|
uv_command pip install --upgrade -r https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/requirements-dev.txt
|
||||||
|
|
||||||
|
# Deactivate the environment
|
||||||
|
deactivate
|
||||||
|
}
|
||||||
|
|
||||||
|
install_toolchains() {
|
||||||
|
# Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
|
||||||
|
local latest_toolchains_release=$(download_url https://api.github.com/repos/qmk/qmk_toolchains/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
# Download the specific release asset with a matching keyword
|
||||||
|
local toolchain_url=$(download_url https://api.github.com/repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep $(fn_os)$(fn_arch))
|
||||||
|
if [ -z "$toolchain_url" ]; then
|
||||||
|
echo "No toolchain found for this OS/Arch combination." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download the toolchain release to the toolchains location
|
||||||
|
echo "Downloading compiler toolchains..." >&2
|
||||||
|
local target_file="$QMK_DISTRIB_DIR/$(basename "$toolchain_url")"
|
||||||
|
download_url "$toolchain_url" "$target_file"
|
||||||
|
|
||||||
|
# Extract the toolchain
|
||||||
|
echo "Extracting compiler toolchains to '$QMK_DISTRIB_DIR'..." >&2
|
||||||
|
tar xf "$target_file" -C "$QMK_DISTRIB_DIR" --strip-components=1
|
||||||
|
}
|
||||||
|
|
||||||
|
install_flashing_tools() {
|
||||||
|
# Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
|
||||||
|
local latest_flashutils_release=$(download_url https://api.github.com/repos/qmk/qmk_flashutils/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
# Download the specific release asset with a matching keyword
|
||||||
|
local flashutils_url=$(download_url https://api.github.com/repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep $(fn_os)$(fn_arch))
|
||||||
|
if [ -z "$flashutils_url" ]; then
|
||||||
|
echo "No flashing tools found for this OS/Arch combination." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download the flashing tools release to the toolchains location
|
||||||
|
echo "Downloading flashing tools..." >&2
|
||||||
|
local target_file="$QMK_DISTRIB_DIR/$(basename "$flashutils_url")"
|
||||||
|
download_url "$flashutils_url" "$target_file"
|
||||||
|
|
||||||
|
# Extract the flashing tools
|
||||||
|
echo "Extracting flashing tools to '$QMK_DISTRIB_DIR'..." >&2
|
||||||
|
tar xf "$target_file" -C "$QMK_DISTRIB_DIR/bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_linux_udev_rules() {
|
||||||
|
# Download the udev rules to the toolchains location
|
||||||
|
echo "Downloading QMK udev rules file..." >&2
|
||||||
|
local qmk_rules_target_file="$QMK_DISTRIB_DIR/50-qmk.rules"
|
||||||
|
download_url "https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/udev/50-qmk.rules" "$qmk_rules_target_file"
|
||||||
|
|
||||||
|
# Install the udev rules -- path list is aligned with qmk doctor's linux.py
|
||||||
|
local udev_rules_paths="
|
||||||
|
/usr/lib/udev/rules.d
|
||||||
|
/usr/local/lib/udev/rules.d
|
||||||
|
/run/udev/rules.d
|
||||||
|
/etc/udev/rules.d
|
||||||
|
"
|
||||||
|
for udev_rules_dir in $udev_rules_paths; do
|
||||||
|
if [ -d "$udev_rules_dir" ]; then
|
||||||
|
echo "Installing udev rules to $udev_rules_dir/50-qmk.rules ..." >&2
|
||||||
|
$(nsudo) mv "$qmk_rules_target_file" "$udev_rules_dir"
|
||||||
|
$(nsudo) chown 0:0 "$udev_rules_dir/50-qmk.rules"
|
||||||
|
$(nsudo) chmod 644 "$udev_rules_dir/50-qmk.rules"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Reload udev rules
|
||||||
|
if command -v udevadm >/dev/null 2>&1; then
|
||||||
|
echo "Reloading udev rules..." >&2
|
||||||
|
$(nsudo) udevadm control --reload-rules
|
||||||
|
$(nsudo) udevadm trigger
|
||||||
|
else
|
||||||
|
echo "udevadm not found, skipping udev rules reload." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_windows_drivers() {
|
||||||
|
# Get the latest driver installer release from https://github.com/qmk/qmk_driver_installer
|
||||||
|
local latest_driver_installer_release=$(download_url https://api.github.com/repos/qmk/qmk_driver_installer/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
# Download the specific release asset
|
||||||
|
local driver_installer_url=$(download_url https://api.github.com/repos/qmk/qmk_driver_installer/releases/tags/$latest_driver_installer_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep '\.exe')
|
||||||
|
if [ -z "$driver_installer_url" ]; then
|
||||||
|
echo "No driver installer found." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Download the driver installer release to the toolchains location
|
||||||
|
echo "Downloading driver installer..." >&2
|
||||||
|
local target_file="$QMK_DISTRIB_DIR/$(basename "$driver_installer_url")"
|
||||||
|
download_url "$driver_installer_url" "$target_file"
|
||||||
|
# Download the drivers list
|
||||||
|
download_url "https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/drivers.txt" "$QMK_DISTRIB_DIR/drivers.txt"
|
||||||
|
# Execute the driver installer
|
||||||
|
cd "$QMK_DISTRIB_DIR"
|
||||||
|
cmd.exe //c "qmk_driver_installer.exe --all --force drivers.txt"
|
||||||
|
cd -
|
||||||
|
# Remove the temporary files
|
||||||
|
rm -f "$QMK_DISTRIB_DIR/qmk_driver_installer.exe" "$QMK_DISTRIB_DIR/drivers.txt" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_tarballs() {
|
||||||
|
# Clean up the tarballs
|
||||||
|
rm -f "$QMK_DISTRIB_DIR"/*.tar.zst || true
|
||||||
|
}
|
||||||
|
|
||||||
|
windows_ish_path() {
|
||||||
|
[ -n "$1" ] || return 0
|
||||||
|
[ "$(uname -o 2>/dev/null || true)" = "Msys" ] && cygpath -w "$1" || echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
posix_ish_path() {
|
||||||
|
[ -n "$1" ] || return 0
|
||||||
|
[ "$(uname -o 2>/dev/null || true)" = "Msys" ] && cygpath -u "$1" || echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set the Python version we want to use with the QMK CLI
|
||||||
|
export PYTHON_TARGET_VERSION=3.13
|
||||||
|
|
||||||
|
# Windows/MSYS doesn't like `/tmp` so we need to set a different temporary directory.
|
||||||
|
# Also set the default `UV_INSTALL_DIR` and `QMK_DISTRIB_DIR` to locations which don't pollute the user's home directory, keeping the installation internal to MSYS.
|
||||||
|
if [ "$(uname -o 2>/dev/null || true)" = "Msys" ]; then
|
||||||
|
export TMPDIR="$(posix_ish_path "$TMP")"
|
||||||
|
export UV_INSTALL_DIR="$(posix_ish_path "${UV_INSTALL_DIR:-/opt/uv}")"
|
||||||
|
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-/opt/qmk}")"
|
||||||
|
export UV_TOOL_DIR="$(posix_ish_path "${UV_TOOL_DIR:-"$UV_INSTALL_DIR/tools"}")"
|
||||||
|
export UV_TOOL_BIN_DIR="$(posix_ish_path "$UV_TOOL_DIR/bin")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
script_parse_args "$@"
|
||||||
|
|
||||||
|
echo "This QMK CLI installation script will install \`uv\`, the QMK CLI, as well as QMK-supplied toolchains and flashing utilities." >&2
|
||||||
|
[ -z "${SKIP_PACKAGE_MANAGER:-}" ] || { preinstall_delay || exit 1; }
|
||||||
|
[ -n "${SKIP_PACKAGE_MANAGER:-}" ] || install_package_manager_deps
|
||||||
|
[ -n "${SKIP_UV:-}" ] || install_uv
|
||||||
|
|
||||||
|
# Make sure the usual `uv` and other associated directories are on the $PATH
|
||||||
|
setup_paths
|
||||||
|
|
||||||
|
# Work out where we want to install the distribution and tools now that `uv` is installed
|
||||||
|
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-$(printf 'import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --python $PYTHON_TARGET_VERSION --with platformdirs -)}")"
|
||||||
|
|
||||||
|
# Clear out the distrib directory if necessary
|
||||||
|
if [ -z "${SKIP_CLEAN:-}" ] || [ -z "${SKIP_QMK_TOOLCHAINS:-}" -a -z "${SKIP_QMK_FLASHUTILS:-}" ]; then
|
||||||
|
if [ -d "$QMK_DISTRIB_DIR" ]; then
|
||||||
|
echo "Removing old QMK distribution..." >&2
|
||||||
|
rm -rf "$QMK_DISTRIB_DIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
mkdir -p "$QMK_DISTRIB_DIR"
|
||||||
|
|
||||||
|
[ -n "${SKIP_QMK_CLI:-}" ] || install_qmk_cli
|
||||||
|
[ -n "${SKIP_QMK_TOOLCHAINS:-}" ] || install_toolchains
|
||||||
|
[ -n "${SKIP_QMK_FLASHUTILS:-}" ] || install_flashing_tools
|
||||||
|
if [ "$(uname -s 2>/dev/null || true)" = "Linux" ]; then
|
||||||
|
[ -n "${SKIP_UDEV_RULES:-}" ] || install_linux_udev_rules
|
||||||
|
fi
|
||||||
|
if [ "$(uname -o 2>/dev/null || true)" = "Msys" ]; then
|
||||||
|
[ -n "${SKIP_WINDOWS_DRIVERS:-}" ] || install_windows_drivers
|
||||||
|
fi
|
||||||
|
clean_tarballs
|
||||||
|
|
||||||
|
# Notify the user that they may need to restart their shell to get the `qmk` command
|
||||||
|
hash -r
|
||||||
|
echo >&2
|
||||||
|
echo "QMK CLI installation complete." >&2
|
||||||
|
echo "The QMK CLI has been installed to '$(posix_ish_path "$(dirname "$(command -v qmk)")")'." >&2
|
||||||
|
echo "The QMK CLI venv has been created at '$(posix_ish_path "$(uv_command tool dir)/qmk")'." >&2
|
||||||
|
echo "Toolchains and flashing utilities have been installed to '$QMK_DISTRIB_DIR'." >&2
|
||||||
|
echo >&2
|
||||||
|
echo "You may need to restart your shell to gain access to the 'qmk' command." >&2
|
||||||
|
echo "Alternatively, add "$(posix_ish_path "$(dirname "$(command -v qmk)")")" to your \$PATH:" >&2
|
||||||
|
echo " export PATH=\"$(posix_ish_path "$(dirname "$(command -v qmk)")"):\$PATH\"" >&2
|
||||||
|
|
||||||
|
} # this ensures the entire script is downloaded #
|
Loading…
Reference in New Issue
Block a user