import { _ as _export_sfc, D as resolveComponent, c as createElementBlock, I as createVNode, w as withCtx, a8 as createStaticVNode, o as openBlock, l as createBaseVNode, a as createTextVNode } from "./chunks/framework.Clpp4x2N.js"; const __pageData = JSON.parse('{"title":"Building QMK with GitHub Userspace","description":"","frontmatter":{},"headers":[],"relativePath":"newbs_building_firmware_workflow.md","filePath":"newbs_building_firmware_workflow.md"}'); const _sfc_main = { name: "newbs_building_firmware_workflow.md" }; const _hoisted_1 = /* @__PURE__ */ createStaticVNode('
This is an intermediate QMK tutorial to setup an out-of-tree build environment with a personal GitHub repository. It avoids using a fork of the QMK firmware to store and build your keymap within its source tree. Keymap files will instead be stored in your own personal GitHub repository, in Userspace format, and built with an action workflow. Unlike the default tutorial, this guide requires some familiarity with using Git.
Is This Guide For Me?
This is a lean setup to avoid space-consuming local build environment in your computer. Troubleshooting compile-time errors will be slower with commit uploads to GitHub for the compiler workflow.
The following are required to get started:
TIP
If you are familiar with using github.dev, you can skip to step 2 and commit the code files that follows directly on GitHub using the web-based VSCode editor.
A working Git client is required for your local operating system to commit and push changes to GitHub.
', 10); const _hoisted_11 = /* @__PURE__ */ createBaseVNode("p", null, [ /* @__PURE__ */ createTextVNode("QMK maintains a bundle of MSYS2, the CLI and all necessary dependencies including Git. Install "), /* @__PURE__ */ createBaseVNode("a", { href: "https://msys.qmk.fm/", target: "_blank", rel: "noreferrer" }, "QMK MSYS"), /* @__PURE__ */ createTextVNode(" with the latest release "), /* @__PURE__ */ createBaseVNode("a", { href: "https://github.com/qmk/qmk_distro_msys/releases/latest", target: "_blank", rel: "noreferrer" }, "here"), /* @__PURE__ */ createTextVNode(". Git will be part of the bundle.") ], -1); const _hoisted_12 = /* @__PURE__ */ createBaseVNode("p", null, [ /* @__PURE__ */ createTextVNode("Install Homebrew following the instructions on "), /* @__PURE__ */ createBaseVNode("a", { href: "https://brew.sh", target: "_blank", rel: "noreferrer" }, "https://brew.sh"), /* @__PURE__ */ createTextVNode(". Git will be part of the bundle.") ], -1); const _hoisted_13 = /* @__PURE__ */ createBaseVNode("p", null, "It's very likely that you already have Git installed. If not, use one of the following commands:", -1); const _hoisted_14 = /* @__PURE__ */ createBaseVNode("ul", null, [ /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Debian / Ubuntu / Devuan: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo apt install -y git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Fedora / Red Hat / CentOS: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo yum -y install git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Arch / Manjaro: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo pacman --needed --noconfirm -S git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Void: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo xbps-install -y git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Solus: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo eopkg -y install git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Sabayon: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo equo install dev-vcs/git") ]), /* @__PURE__ */ createBaseVNode("li", null, [ /* @__PURE__ */ createTextVNode("Gentoo: "), /* @__PURE__ */ createBaseVNode("code", null, "sudo emerge dev-vcs/git") ]) ], -1); const _hoisted_15 = /* @__PURE__ */ createStaticVNode('If your GitHub account is not configured for authenticated Git operations, you will need to setup at least one of the following:
You will need a personal GitHub repository to host your QMK code. Follow this guide to create one named qmk_keymap
. Do not proceed to commit any files just yet.
Run the following commands in your computer to create a folder with a few template files:
mkdir -p ~/qmk_keymap/.github/workflows\ntouch ~/qmk_keymap/.github/workflows/build.yml\ntouch ~/qmk_keymap/config.h\necho "SRC += source.c" > ~/qmk_keymap/rules.mk\necho "#include QMK_KEYBOARD_H" > ~/qmk_keymap/source.c
TIP
For Windows user running MSYS, those commands will create the folder qmk_keymap/
and its content in the C:\\Users\\<windows_username>\\qmk_keymap\\
path location.
Visit the QMK Configurator to create a keymap file:
~/qmk_keymap/
folder.WARNING
Important: Make sure that the GitHub username you use in step 2 is correct. If it is not, the build process will fail to locate your files in the right folder.
Open the file ~/qmk_keymap/.github/workflows/build.yml
with your favorite text editor, paste the following workflow content, and save it:
name: Build QMK firmware\non: [push, workflow_dispatch]\n\njobs:\n build:\n runs-on: ubuntu-latest\n container: ghcr.io/qmk/qmk_cli\n strategy:\n fail-fast: false\n matrix:\n# List of keymap json files to build\n file:\n - username.json\n# End of json file list\n\n steps:\n\n - name: Disable git safe directory checks\n run : git config --global --add safe.directory '*'\n\n - name: Checkout QMK\n uses: actions/checkout@v3\n with:\n repository: qmk/qmk_firmware\n submodules: recursive\n\n - name: Checkout userspace\n uses: actions/checkout@v3\n with:\n path: users/${{ github.actor }}\n\n - name: Build firmware\n run: qmk compile "users/${{ github.actor }}/${{ matrix.file }}"\n\n - name: Archive firmware\n uses: actions/upload-artifact@v3\n continue-on-error: true\n with:\n name: ${{ matrix.file }}_${{ github.actor }}\n path: |\n *.hex\n *.bin\n *.uf2
Replace username.json
with the JSON file name that was downloaded from QMK Configurator in the previous step.
WARNING
Do note that the build.yml
file requires proper indentation for every line. Incorrect spacing will trigger workflow syntax errors.
If you have completed all steps correctly, the folder qmk_keymap/
will contain the following files:
├── .github\n│ └── workflows\n│ └── build.yml\n├── rules.mk\n├── config.h\n├── source.c\n└── username.json
To commit and push them into GitHub, run the following commands (replacing gh-username
with your GitHub user name):
cd ~/qmk_keymap\ngit init\ngit add -A\ngit commit -m "Initial QMK keymap commit"\ngit branch -M main\ngit remote add origin https://github.com/gh-username/qmk_keymap.git\ngit push -u origin main
TIP
Use your GitHub personal access token at the password prompt. If you have setup SSH access, replace https://github.com/gh-username/qmk_keymap.git
with git@github.com:gh-username/qmk_keymap.git
in the remote origin command above.
Files committed to GitHub in the previous step will automatically trigger the workflow to build the JSON file listed in build.yml
. To review its output:
Download and flash the firmware file into your keyboard using QMK Toolbox.
This setup and workflow relies on the QMK Userspace feature. The build process will copy the QMK source codes and clone your repository into its users/
folder in a container. You must adhere to the following guidelines when customising your keymaps:
keymap.c
.process_record_user()
) can be placed in the source.c
file.matrix.file:
, e.g.: file:\n - planck.json\n - crkbd.json
TIP
See GitHub Actions guide to learn more about development workflow.