├── .devcontainer ├── .devenv │ └── .gitignore ├── .direnv │ └── .gitignore └── devcontainer.json ├── .envrc ├── .github ├── CODEOWNERS ├── actions │ ├── build │ │ └── action.yaml │ ├── infra-repo-update │ │ └── action.yaml │ ├── query │ │ └── action.yaml │ └── setup │ │ └── action.yaml ├── dependabot.yaml └── workflows │ ├── build.yaml │ ├── check_linked_issue.yaml │ ├── ci-request-review.yaml │ ├── dependabot.yaml │ ├── docs.yaml │ ├── infra-repo-update-production.yaml │ ├── infra-repo-update-test.yaml │ ├── new_version.yaml │ └── release.yaml ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── Makefile.custom ├── README.md ├── book.toml ├── debian ├── .gitignore ├── changelog ├── compat ├── control ├── copyright ├── rsdk.docs ├── rsdk.install ├── rsdk.lintian-overrides ├── rules └── source │ ├── format │ └── lintian-overrides ├── debs └── .gitignore ├── devenv.local.nix.example ├── devenv.lock ├── devenv.nix ├── devenv.yaml ├── docs ├── SUMMARY.md ├── cmd │ ├── rsdk-build.md │ ├── rsdk-chroot.md │ ├── rsdk-install.md │ ├── rsdk-shell.md │ └── rsdk.md ├── install │ ├── deb.md │ ├── devcontainer.md │ ├── native.md │ └── vscode.md ├── intro.md ├── tutorials │ ├── customize.md │ ├── global_options.md │ ├── local_pkg.md │ ├── migration.md │ ├── new_device.md │ └── usage.md └── why.md ├── package-lock.json ├── package.json ├── po ├── .gitignore ├── messages.pot └── zh-CN.po ├── src ├── .gitignore ├── bin │ └── rsdk ├── lib │ └── rsdk │ │ ├── stdlib.sh │ │ └── utils.sh ├── libexec │ └── rsdk │ │ ├── rsdk-build │ │ ├── rsdk-chroot │ │ ├── rsdk-config │ │ ├── rsdk-devcon │ │ ├── rsdk-help │ │ ├── rsdk-infra-build │ │ ├── rsdk-infra-package-update │ │ ├── rsdk-infra-pkg-download │ │ ├── rsdk-infra-pkg-snapshot │ │ ├── rsdk-infra-product-build │ │ ├── rsdk-infra-product-update │ │ ├── rsdk-infra-repo-build │ │ ├── rsdk-infra-repo-sync │ │ ├── rsdk-infra-repo-update │ │ ├── rsdk-infra-update │ │ ├── rsdk-install │ │ ├── rsdk-setup │ │ ├── rsdk-shell │ │ ├── rsdk-tui │ │ ├── rsdk-welcome │ │ └── rsdk-write-image └── share │ ├── bash-completion │ └── completions │ │ └── rsdk │ ├── man │ └── man8 │ │ ├── .gitignore │ │ └── rsdk.8.md │ └── rsdk │ ├── build │ ├── image.jsonnet │ ├── mod │ │ ├── additional_repos.libjsonnet │ │ ├── cleanup.libjsonnet │ │ ├── distro.libjsonnet │ │ ├── packages.libjsonnet │ │ ├── packages │ │ │ ├── categories │ │ │ │ ├── base.libjsonnet │ │ │ │ ├── core.libjsonnet │ │ │ │ └── desktop.libjsonnet │ │ │ ├── cli.libjsonnet │ │ │ ├── core.libjsonnet │ │ │ ├── gdm.libjsonnet │ │ │ ├── gnome.libjsonnet │ │ │ ├── i3.libjsonnet │ │ │ ├── kde.libjsonnet │ │ │ ├── sway.libjsonnet │ │ │ └── xfce.libjsonnet │ │ └── vscodium.libjsonnet │ └── rootfs.jsonnet │ ├── common │ ├── check_linked_issue │ │ └── check_linked_issue.yaml.jsonnet │ ├── codeowners │ │ └── CODEOWNERS.jsonnet │ ├── dependabot │ │ ├── dependabot.yaml.jsonnet │ │ └── workflow.jsonnet │ ├── licenses │ │ └── GPLv3.jsonnet │ └── repo_rulesets │ │ └── default.json │ ├── configs │ ├── distributions.json │ ├── distro_check.libjsonnet │ ├── product_data.libjsonnet │ ├── product_firmware_type.libjsonnet │ ├── product_partition_table_type.libjsonnet │ ├── product_soc.libjsonnet │ ├── products.json │ ├── rsdk.json │ ├── soc_family.libjsonnet │ ├── soc_specific_repo.libjsonnet │ └── socs.json │ ├── infra-package │ ├── .devcontainer │ │ ├── .devenv │ │ │ └── .gitignore │ │ ├── .direnv │ │ │ └── .gitignore │ │ └── devcontainer.json │ ├── .envrc │ ├── .github │ │ └── workflows │ │ │ ├── docs.yaml.jsonnet │ │ │ ├── new_version.yaml.jsonnet │ │ │ └── release.yaml.jsonnet │ ├── .gitignore │ ├── Makefile.linux.jsonnet │ ├── Makefile.u-boot.jsonnet │ ├── README.md.jsonnet │ ├── debian │ │ ├── .gitignore │ │ ├── changelog.jsonnet │ │ ├── common-lintian-overrides │ │ ├── compat │ │ ├── control.linux.jsonnet │ │ ├── control.u-boot.jsonnet │ │ ├── copyright.jsonnet │ │ ├── patches │ │ │ ├── linux │ │ │ │ └── 0001-feat-Radxa-common-kernel-config.patch │ │ │ └── series.linux │ │ ├── rules │ │ ├── source │ │ │ └── format │ │ └── u-boot.install │ ├── devenv.lock │ ├── devenv.nix │ └── template.jsonnet │ ├── infra-product │ ├── .github │ │ └── workflows │ │ │ └── workflow.jsonnet │ ├── README.md.jsonnet │ └── template.jsonnet │ └── infra-repo │ ├── .github │ └── workflows │ │ ├── build.yaml.jsonnet │ │ └── update.yaml.jsonnet │ ├── README.md.jsonnet │ ├── pkgs.lock.jsonnet │ └── template.jsonnet └── theme ├── book.js ├── css ├── chrome.css ├── general.css ├── language-picker.css ├── mdbook-admonish.css ├── print.css └── variables.css ├── favicon.png ├── favicon.svg ├── fonts ├── OPEN-SANS-LICENSE.txt ├── SOURCE-CODE-PRO-LICENSE.txt ├── fonts.css ├── open-sans-v17-all-charsets-300.woff2 ├── open-sans-v17-all-charsets-300italic.woff2 ├── open-sans-v17-all-charsets-600.woff2 ├── open-sans-v17-all-charsets-600italic.woff2 ├── open-sans-v17-all-charsets-700.woff2 ├── open-sans-v17-all-charsets-700italic.woff2 ├── open-sans-v17-all-charsets-800.woff2 ├── open-sans-v17-all-charsets-800italic.woff2 ├── open-sans-v17-all-charsets-italic.woff2 ├── open-sans-v17-all-charsets-regular.woff2 └── source-code-pro-v11-all-charsets-500.woff2 ├── highlight.css ├── highlight.js └── index.hbs /.devcontainer/.devenv/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /.devcontainer/.direnv/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "customizations": { 3 | "vscode": { 4 | "settings": { 5 | "terminal.integrated.defaultProfile.linux": "bash" 6 | }, 7 | "extensions": [ 8 | "mkhl.direnv", 9 | "github.vscode-github-actions", 10 | "grafana.vscode-jsonnet", 11 | "ms-vscode.makefile-tools", 12 | "vivaxy.vscode-conventional-commits" 13 | ] 14 | } 15 | }, 16 | "image": "mcr.microsoft.com/devcontainers/base:jammy", 17 | "features": { 18 | "ghcr.io/devcontainers/features/nix:1": { 19 | "version": "2.21.0", 20 | "packages": [ 21 | "direnv", 22 | "devenv" 23 | ], 24 | "extraNixConfig": [ 25 | "experimental-features = nix-command flakes", 26 | // Uncomment below to speed up container building in China 27 | // "substituters = https://mirrors.ustc.edu.cn/nix-channels/store https://devenv.cachix.org https://cache.nixos.org", 28 | "trusted-users = root vscode" 29 | ] 30 | } 31 | }, 32 | "mounts": [ 33 | { 34 | "source": "${localWorkspaceFolder}/.devcontainer/.devenv", 35 | "target": "${containerWorkspaceFolder}/.devenv", 36 | "type": "bind" 37 | }, 38 | { 39 | "source": "${localWorkspaceFolder}/.devcontainer/.direnv", 40 | "target": "${containerWorkspaceFolder}/.direnv", 41 | "type": "bind" 42 | } 43 | ], 44 | "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind,consistency=cached", 45 | "runArgs": [ 46 | // https://github.com/moby/moby/issues/27195#issuecomment-1410745778 47 | "--ulimit", "nofile=1024:524288", 48 | // Needed for root mode 49 | // https://gitlab.mister-muffin.de/josch/mmdebstrap/src/branch/main/mmdebstrap#L4970 50 | "--cap-add", "SYS_ADMIN", 51 | // **************************************** 52 | // OPTIONAL FEATURES 53 | // **************************************** 54 | // Needed for kpartx to mount and unmount target image 55 | // https://serverfault.com/a/701427 56 | // https://stackoverflow.com/a/58953658 57 | // Require /dev mapped inside for accessing newly created loop devices 58 | // Only enable this if you need to work with loop devices, as disk images 59 | // are not created with kpartx anymore. 60 | // Alternatively, if you want to use rsdk write-image, you also need this to 61 | // be enabled. 62 | "--privileged", 63 | // Needed for guestfish to accelerate VM for disk operation 64 | // Usually covered by /dev mapping. 65 | // "--device", "/dev/kvm", 66 | // Needed to write to raw disks 67 | "-v", "/dev:/dev" 68 | ], 69 | "overrideCommand": true, 70 | "updateContentCommand": "command -v devenv && devenv test || true", 71 | "postCreateCommand": "src/bin/rsdk setup && make devcontainer_setup" 72 | } 73 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" 2 | 3 | use devenv -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Catch-all code owner 2 | * @RadxaYuntian 3 | 4 | # Disown CI yaml so automerge can work 5 | # https://github.com/orgs/community/discussions/23064#discussioncomment-8383923 6 | .github/actions/**/*.yaml 7 | .github/workflows/*.yaml 8 | -------------------------------------------------------------------------------- /.github/actions/infra-repo-update/action.yaml: -------------------------------------------------------------------------------- 1 | name: 'infra-repo-update' 2 | description: 'Radxa apt repos management' 3 | inputs: 4 | test-repo: 5 | default: false 6 | token: 7 | required: true 8 | runs: 9 | using: "composite" 10 | steps: 11 | - name: Query suites info 12 | id: query 13 | uses: RadxaOS-SDK/rsdk/.github/actions/query@main 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | repository: RadxaOS-SDK/rsdk 18 | path: .tmp/rsdk 19 | - name: Dispatch workflow 20 | env: 21 | GH_TOKEN: ${{ inputs.token }} 22 | shell: bash 23 | run: | 24 | if [[ "${{ inputs.test-repo }}" == "true" ]] 25 | then 26 | repo_suffix="-test" 27 | else 28 | repo_suffix="" 29 | fi 30 | 31 | repo_org="$(.tmp/rsdk/src/bin/rsdk config infra.organizations.repository)" 32 | supported_distros=() 33 | mapfile -t supported_distros < <(jq -er .[] <<< '${{ steps.query.outputs.suites }}') 34 | 35 | for distro in "${supported_distros[@]}" 36 | do 37 | if gh repo view "$repo_org/$distro$repo_suffix" &>/dev/null; then 38 | gh workflow run .github/workflows/update.yaml --repo "$repo_org/$distro$repo_suffix" 39 | else 40 | echo "$repo_org/$distro$repo_suffix does not exist. Skip." 41 | fi 42 | done 43 | -------------------------------------------------------------------------------- /.github/actions/query/action.yaml: -------------------------------------------------------------------------------- 1 | name: rsdk-query 2 | description: rsdk product information query Action 3 | inputs: 4 | product: 5 | required: false 6 | outputs: 7 | suites: 8 | value: ${{ steps.query.outputs.suites }} 9 | editions: 10 | value: ${{ steps.query.outputs.editions }} 11 | runs: 12 | using: "composite" 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | repository: RadxaOS-SDK/rsdk 18 | path: .tmp/rsdk 19 | - name: Set suite based on input variables 20 | id: query 21 | shell: bash 22 | run: | 23 | if [[ -n "${{ inputs.product }}" ]]; then 24 | echo "suites=$(jq -ec '. | map(select(.product == "${{ inputs.product }}"))[].supported_suite' .tmp/rsdk/src/share/rsdk/configs/products.json)" >> $GITHUB_OUTPUT 25 | echo "editions=$(jq -ec '. | map(select(.product == "${{ inputs.product }}"))[].supported_edition' .tmp/rsdk/src/share/rsdk/configs/products.json)" >> $GITHUB_OUTPUT 26 | else 27 | echo "suites=$(jq -ec '[ .[].supported_suites ] | add' .tmp/rsdk/src/share/rsdk/configs/distributions.json)" >> $GITHUB_OUTPUT 28 | fi 29 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yaml: -------------------------------------------------------------------------------- 1 | name: rsdk-setup 2 | description: rsdk setup Action 3 | runs: 4 | using: "composite" 5 | steps: 6 | - name: Checkout 7 | uses: actions/checkout@v4 8 | with: 9 | repository: RadxaOS-SDK/rsdk 10 | submodules: recursive 11 | - name: Enable KVM group perms 12 | shell: bash 13 | run: | 14 | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules 15 | sudo udevadm control --reload-rules 16 | sudo udevadm trigger --name-match=kvm 17 | - name: Set up QEMU Emulation 18 | uses: docker/setup-qemu-action@v3 19 | with: 20 | image: tonistiigi/binfmt:latest 21 | - name: rsdk-welcome 22 | uses: devcontainers/ci@v0.3 23 | with: 24 | push: never 25 | runCmd: | 26 | src/bin/rsdk welcome 27 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build images 2 | 3 | on: 4 | merge_group: 5 | pull_request: 6 | paths-ignore: 7 | - '**.md' 8 | - .gitignore 9 | - 'docs/**' 10 | - 'theme/**' 11 | - 'po/**' 12 | - book.toml 13 | - .github/workflows/docs.yaml 14 | push: 15 | branches-ignore: 16 | - 'dependabot/**' 17 | paths-ignore: 18 | - '**.md' 19 | - .gitignore 20 | - 'docs/**' 21 | - 'theme/**' 22 | - 'po/**' 23 | - book.toml 24 | - .github/workflows/docs.yaml 25 | schedule: 26 | - cron: '0 0 * * SUN' 27 | workflow_dispatch: 28 | 29 | concurrency: 30 | group: ${{ github.workflow }}-${{ github.ref }} 31 | cancel-in-progress: true 32 | 33 | jobs: 34 | query: 35 | runs-on: ubuntu-latest 36 | outputs: 37 | products: ${{ steps.query.outputs.products }} 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@v4 41 | - name: Query available board configs 42 | id: query 43 | run: | 44 | echo "products=$(jq -c '. | map(.product)' src/share/rsdk/configs/products.json)" >> $GITHUB_OUTPUT 45 | build-images: 46 | needs: [ query ] 47 | runs-on: ubuntu-22.04 48 | strategy: 49 | fail-fast: false 50 | max-parallel: 10 51 | matrix: 52 | products: ${{ fromJSON(needs.query.outputs.products) }} 53 | steps: 54 | - name: Checkout 55 | uses: actions/checkout@v4 56 | - name: Build ${{ matrix.products }} 57 | uses: ./.github/actions/build 58 | with: 59 | product: ${{ matrix.products }} 60 | test-repo: true 61 | artifacts: true 62 | -------------------------------------------------------------------------------- /.github/workflows/check_linked_issue.yaml: -------------------------------------------------------------------------------- 1 | jobs: 2 | check_pull_requests: 3 | name: "Check linked issues" 4 | permissions: 5 | issues: "write" 6 | pull-requests: "write" 7 | runs-on: "ubuntu-latest" 8 | steps: 9 | - name: "Check linked issues" 10 | uses: "nearform-actions/github-action-check-linked-issues@v1" 11 | name: "Check linked issues" 12 | "on": 13 | pull_request_target: 14 | types: 15 | - "opened" 16 | - "reopened" 17 | permissions: {} 18 | -------------------------------------------------------------------------------- /.github/workflows/ci-request-review.yaml: -------------------------------------------------------------------------------- 1 | name: Request review for CI files 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | paths: 8 | - '.github/actions/**/*.yaml' 9 | - '.github/workflows/*.yaml' 10 | 11 | permissions: 12 | pull-requests: write 13 | 14 | jobs: 15 | request-review: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/github-script@v7 20 | with: 21 | github-token: ${{ secrets.GITHUB_TOKEN }} 22 | script: |- 23 | const reviewers = ['RadxaYuntian']; 24 | await github.rest.pulls.requestReviewers({ 25 | owner: context.repo.owner, 26 | repo: context.repo.repo, 27 | pull_number: context.issue.number, 28 | reviewers: reviewers 29 | }); 30 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yaml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: github.actor == 'dependabot[bot]' 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v2 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - name: Approve a PR & Enable auto-merge for Dependabot PRs 19 | run: | 20 | gh pr review --approve "$PR_URL" 21 | gh pr merge --auto --merge "$PR_URL" 22 | env: 23 | PR_URL: ${{github.event.pull_request.html_url}} 24 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 25 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation 2 | on: 3 | merge_group: 4 | pull_request: 5 | paths: 6 | - 'docs/**' 7 | - 'theme/**' 8 | - 'po/**' 9 | - book.toml 10 | - .github/workflows/docs.yaml 11 | push: 12 | branches: 13 | - main 14 | paths: 15 | - 'docs/**' 16 | - 'theme/**' 17 | - 'po/**' 18 | - book.toml 19 | - .github/workflows/docs.yaml 20 | workflow_dispatch: 21 | 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.ref }} 24 | cancel-in-progress: true 25 | 26 | permissions: 27 | pages: write 28 | id-token: write 29 | 30 | jobs: 31 | build-doc: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | with: 37 | fetch-depth: 0 38 | - name: Setup mdBook 39 | uses: peaceiris/actions-mdbook@v2 40 | with: 41 | mdbook-version: 'latest' 42 | - name: Install mdbook plugins 43 | shell: bash 44 | run: | 45 | for i in mdbook-admonish mdbook-linkcheck mdbook-i18n-helpers mdbook-toc mdbook-cmdrun 46 | do 47 | cargo install "$i" 48 | done 49 | - name: Build 50 | run: | 51 | mdbook build 52 | for po_lang in zh-CN 53 | do 54 | POT_CREATION_DATE=$(grep --max-count 1 '^"POT-Creation-Date:' po/$po_lang.po | sed -E 's/".*: (.*)\\n"/\1/') 55 | if [[ $POT_CREATION_DATE == "" ]]; then 56 | POT_CREATION_DATE=now 57 | fi 58 | echo "::group::Building $po_lang translation as of $POT_CREATION_DATE" 59 | rm -r docs/ 60 | git restore --source "$(git rev-list -n 1 --before "$POT_CREATION_DATE" @)" docs/ 61 | 62 | # Set language and adjust site URL. Clear the redirects 63 | # since they are in sync with the source files, not the 64 | # translation. 65 | MDBOOK_BOOK__LANGUAGE=$po_lang \ 66 | MDBOOK_OUTPUT__HTML__SITE_URL=/rsdk/$po_lang/ \ 67 | MDBOOK_OUTPUT__HTML__REDIRECT='{}' \ 68 | mdbook build -d book/$po_lang 69 | mv book/$po_lang/html book/html/$po_lang 70 | echo "::endgroup::" 71 | done 72 | - name: Setup Pages 73 | uses: actions/configure-pages@v5 74 | - name: Upload artifact 75 | uses: actions/upload-pages-artifact@v3 76 | with: 77 | # Upload entire repository 78 | path: "./book/html" 79 | - name: Deploy to GitHub Pages 80 | id: deployment 81 | uses: actions/deploy-pages@v4 82 | if: github.event_name != 'pull_request' 83 | -------------------------------------------------------------------------------- /.github/workflows/infra-repo-update-production.yaml: -------------------------------------------------------------------------------- 1 | name: Update Production repos 2 | on: 3 | workflow_dispatch: 4 | 5 | permissions: {} 6 | 7 | jobs: 8 | update-prod: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Update Production repos 14 | uses: ./.github/actions/infra-repo-update 15 | with: 16 | token: ${{ secrets.RSDK_APT_REPOSITORY_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/infra-repo-update-test.yaml: -------------------------------------------------------------------------------- 1 | name: Update Test repos 2 | on: 3 | workflow_dispatch: 4 | 5 | permissions: {} 6 | 7 | jobs: 8 | update-test: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Update Test repos 14 | uses: ./.github/actions/infra-repo-update 15 | with: 16 | test-repo: true 17 | token: ${{ secrets.RSDK_APT_REPOSITORY_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/new_version.yaml: -------------------------------------------------------------------------------- 1 | jobs: 2 | release: 3 | permissions: 4 | contents: "write" 5 | runs-on: "ubuntu-latest" 6 | steps: 7 | - name: "Checkout" 8 | uses: "actions/checkout@v4" 9 | with: 10 | fetch-depth: 0 11 | submodules: "recursive" 12 | token: "${{secrets.GIT_PUSH_TOKEN}}" 13 | - if: "github.event.inputs.update == 'true'" 14 | name: "Update submodules" 15 | run: | 16 | git config user.name "github-actions[bot]" 17 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 18 | git submodule update --remote 19 | if git diff --quiet; then 20 | echo "Submodules are the latest. Nothing to update." 21 | exit 22 | fi 23 | git add . 24 | git commit -m "chore: update submodules" 25 | shell: "bash" 26 | - name: "Set up QEMU Emulation" 27 | uses: "docker/setup-qemu-action@v3" 28 | with: 29 | image: "tonistiigi/binfmt:latest" 30 | - name: "Test" 31 | uses: "devcontainers/ci@v0.3" 32 | with: 33 | push: "never" 34 | runCmd: | 35 | sudo apt-get update 36 | sudo apt-get install --no-install-recommends -y git-buildpackage 37 | export DEBEMAIL="dev@radxa.com" 38 | export DEBFULLNAME='"Radxa Computer Co., Ltd"' 39 | git config user.name "github-actions[bot]" 40 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 41 | make dch 42 | make test deb 43 | - if: "github.event.inputs.release == 'true'" 44 | name: "Push" 45 | run: | 46 | git push 47 | shell: "bash" 48 | name: "Create release" 49 | "on": 50 | workflow_dispatch: 51 | inputs: 52 | release: 53 | default: true 54 | description: "Release new version" 55 | required: true 56 | type: "boolean" 57 | update: 58 | default: false 59 | description: "Update submodule" 60 | required: true 61 | type: "boolean" 62 | permissions: {} 63 | run-name: "${{ inputs.update && 'Update submodule' || '' }}${{ inputs.update && inputs.release && ' & ' || '' }}${{ inputs.release && 'Release new version' }}${{ !inputs.update && !inputs.release && 'Test for new release' || '' }}" 64 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | jobs: 2 | build: 3 | outputs: 4 | distro: "${{ steps.distro_check.outputs.distro }}" 5 | runs-on: "ubuntu-latest" 6 | steps: 7 | - name: "Checkout" 8 | uses: "actions/checkout@v4" 9 | with: 10 | fetch-depth: 0 11 | fetch-tags: true 12 | submodules: "recursive" 13 | - name: "Set up QEMU Emulation" 14 | uses: "docker/setup-qemu-action@v3" 15 | with: 16 | image: "tonistiigi/binfmt:latest" 17 | - name: "Test" 18 | uses: "devcontainers/ci@v0.3" 19 | with: 20 | push: "never" 21 | runCmd: | 22 | sudo apt-get update 23 | sudo apt-get install --no-install-recommends -y git-buildpackage 24 | export DEBEMAIL="dev@radxa.com" 25 | export DEBFULLNAME='"Radxa Computer Co., Ltd"' 26 | git config user.name "github-actions[bot]" 27 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 28 | git branch -m GITHUB_RUNNER || true 29 | git branch -D main || true 30 | git switch -c main || true 31 | make dch 32 | make test deb 33 | git reset --hard HEAD~1 34 | rm ../*.deb 35 | - name: "Build" 36 | uses: "devcontainers/ci@v0.3" 37 | with: 38 | push: "never" 39 | runCmd: | 40 | make deb 41 | - id: "artifacts_path" 42 | name: "Workaround actions/upload-artifact#176" 43 | run: | 44 | echo "artifacts_path=$(realpath ..)" >> "$GITHUB_OUTPUT" 45 | shell: "bash" 46 | - name: "Upload artifacts" 47 | uses: "actions/upload-artifact@v4" 48 | with: 49 | name: "${{ github.event.repository.name }}" 50 | path: | 51 | ${{ steps.artifacts_path.outputs.artifacts_path }}/*.deb 52 | - id: "distro_check" 53 | name: "Check if the latest version is releasable" 54 | run: | 55 | version="$(dpkg-parsechangelog -S Version)" 56 | version="${version//\~/.}" 57 | if [[ -n "$(git tag -l "$version")" ]] 58 | then 59 | echo "distro=UNRELEASED" >> "$GITHUB_OUTPUT" 60 | else 61 | echo "distro=$(dpkg-parsechangelog -S Distribution)" >> "$GITHUB_OUTPUT" 62 | fi 63 | shell: "bash" 64 | release: 65 | if: "${{ github.event_name != 'pull_request' && needs.build.outputs.distro != 'UNRELEASED' }}" 66 | needs: "build" 67 | permissions: 68 | contents: "write" 69 | runs-on: "ubuntu-latest" 70 | steps: 71 | - name: "Checkout" 72 | uses: "actions/checkout@v4" 73 | - name: "Download generated debs" 74 | uses: "actions/download-artifact@v4" 75 | with: 76 | name: "${{ github.event.repository.name }}" 77 | path: ".artifacts" 78 | - name: "Prepare for release" 79 | run: | 80 | version="$(dpkg-parsechangelog -S Version)" 81 | version="${version//\~/.}" 82 | echo "version=$version" >> $GITHUB_ENV 83 | echo "changes<> $GITHUB_ENV 84 | echo '```' >> $GITHUB_ENV 85 | echo "$(dpkg-parsechangelog -S Changes)" >> $GITHUB_ENV 86 | echo '```' >> $GITHUB_ENV 87 | echo "EOF" >> $GITHUB_ENV 88 | echo "$version" > VERSION 89 | if [[ -f pkg.conf.template ]] 90 | then 91 | sed "s/VERSION/$version/g" pkg.conf.template > pkg.conf 92 | fi 93 | shell: "bash" 94 | - name: "Release" 95 | uses: "softprops/action-gh-release@v2" 96 | with: 97 | body_path: "README.md" 98 | draft: false 99 | fail_on_unmatched_files: false 100 | files: | 101 | .artifacts/**/*.deb 102 | pkg.conf 103 | VERSION 104 | prerelease: false 105 | tag_name: "${{ env.version }}" 106 | target_commitish: "${{ github.sha }}" 107 | token: "${{ secrets.GITHUB_TOKEN }}" 108 | - name: "Append changelog" 109 | uses: "softprops/action-gh-release@v2" 110 | with: 111 | append_body: true 112 | body: | 113 | ## Changelog for ${{ env.version }} 114 | ${{ env.changes }} 115 | tag_name: "${{ env.version }}" 116 | - name: "Update Test repos" 117 | uses: "RadxaOS-SDK/rsdk/.github/actions/infra-repo-update@main" 118 | with: 119 | test-repo: true 120 | token: "${{ secrets.RADXA_APT_TEST_REPO_TOKEN }}" 121 | name: "Build & Release" 122 | "on": 123 | merge_group: {} 124 | pull_request: 125 | paths-ignore: 126 | - "docs/**" 127 | - "theme/**" 128 | - "po/**" 129 | - "book.toml" 130 | - ".github/workflows/docs.yaml" 131 | push: 132 | branches: 133 | - "main" 134 | paths-ignore: 135 | - "docs/**" 136 | - "theme/**" 137 | - "po/**" 138 | - "book.toml" 139 | - ".github/workflows/docs.yaml" 140 | workflow_dispatch: {} 141 | permissions: {} 142 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Devenv 2 | /.devenv* 3 | /devenv.local.nix 4 | 5 | # direnv 6 | /.direnv 7 | 8 | # pre-commit 9 | /.pre-commit-config.yaml 10 | 11 | # node.js 12 | /node_modules 13 | 14 | # Build output 15 | /out 16 | 17 | # Local VS Code configuration 18 | /.vscode* 19 | 20 | # mdbook build output 21 | /book 22 | 23 | # Local rsdk config 24 | .rsdk.json 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "keyrings/debian"] 2 | path = externals/keyrings/debian 3 | url = https://salsa.debian.org/release-team/debian-archive-keyring.git 4 | [submodule "keyrings/ubuntu"] 5 | path = externals/keyrings/ubuntu 6 | url = https://git.launchpad.net/ubuntu/+source/ubuntu-keyring 7 | [submodule "keyrings/radxa"] 8 | path = externals/keyrings/radxa 9 | url = https://github.com/radxa-pkg/radxa-archive-keyring.git 10 | [submodule "keyrings/vscodium"] 11 | path = externals/keyrings/vscodium 12 | url = https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo.git 13 | [submodule "externals/librtui"] 14 | path = externals/librtui 15 | url = https://github.com/radxa-pkg/librtui.git 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include Makefile.custom 2 | 3 | .PHONY: all 4 | all: build 5 | 6 | .PHONY: devcontainer_setup 7 | devcontainer_setup: 8 | sudo dpkg --add-architecture arm64 9 | sudo apt-get update 10 | sudo apt-get build-dep . -y 11 | 12 | # 13 | # Test 14 | # 15 | .PHONY: test 16 | test: 17 | 18 | # 19 | # Build 20 | # 21 | .PHONY: build 22 | build: build-man build-doc 23 | 24 | SRC-MAN := src/share/man/man8 25 | SRCS-MAN := $(wildcard $(SRC-MAN)/*.md) 26 | MANS := $(SRCS-MAN:.md=) 27 | .PHONY: build-man 28 | build-man: $(MANS) 29 | 30 | $(SRC-MAN)/%: $(SRC-MAN)/%.md 31 | pandoc "$<" -o "$@" --from markdown --to man -s 32 | 33 | SRC-DOC := src 34 | DOCS := $(SRC-DOC)/SOURCE 35 | .PHONY: build-doc 36 | build-doc: $(DOCS) 37 | 38 | $(SRC-DOC): 39 | mkdir -p $(SRC-DOC) 40 | 41 | .PHONY: $(SRC-DOC)/SOURCE 42 | $(SRC-DOC)/SOURCE: $(SRC-DOC) 43 | echo -e "git clone $(shell git remote get-url origin)\ngit checkout $(shell git rev-parse HEAD)" > "$@" 44 | 45 | # 46 | # Documentation 47 | # 48 | .PHONY: serve 49 | serve: 50 | mdbook serve 51 | 52 | .PHONY: serve_zh-CN 53 | serve_zh-CN: 54 | MDBOOK_BOOK__LANGUAGE=zh-CN mdbook serve -d book/zh-CN 55 | 56 | .PHONY: translate 57 | translate: 58 | MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' mdbook build -d po 59 | for i in po/*.po; \ 60 | do \ 61 | msgmerge --update $$i po/messages.pot; \ 62 | done 63 | 64 | .PHONY: update-admonish 65 | update-admonish: 66 | mdbook-admonish install --css-dir theme/css 67 | 68 | # 69 | # Clean 70 | # 71 | .PHONY: distclean 72 | distclean: clean 73 | 74 | .PHONY: clean 75 | clean: clean-man clean-doc clean-deb 76 | 77 | .PHONY: clean-man 78 | clean-man: 79 | rm -rf $(MANS) 80 | 81 | .PHONY: clean-doc 82 | clean-doc: 83 | rm -rf $(DOCS) 84 | 85 | .PHONY: clean-deb 86 | clean-deb: 87 | rm -rf debian/.debhelper debian/${PROJECT}*/ debian/debhelper-build-stamp debian/files debian/*.debhelper.log debian/*.postrm.debhelper debian/*.substvars 88 | 89 | # 90 | # Release 91 | # 92 | .PHONY: dch 93 | dch: debian/changelog 94 | gbp dch --ignore-branch --multimaint-merge --release --spawn-editor=never \ 95 | --git-log='--no-merges --perl-regexp --invert-grep --grep=^(chore:\stemplates\sgenerated)' \ 96 | --dch-opt=--upstream --commit --commit-msg="feat: release %(version)s" 97 | 98 | .PHONY: deb 99 | deb: debian 100 | debuild --no-lintian --lintian-hook "lintian --fail-on error,warning --suppress-tags bad-distribution-in-changes-file -- %p_%v_*.changes" --no-sign -b 101 | -------------------------------------------------------------------------------- /Makefile.custom: -------------------------------------------------------------------------------- 1 | PROJECT ?= rsdk 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rsdk - RadxaOS Software Development Kit 2 | 3 | [![Build images](https://github.com/RadxaOS-SDK/rsdk/actions/workflows/build.yaml/badge.svg)](https://github.com/RadxaOS-SDK/rsdk/actions/workflows/build.yaml) [![Deploy documentation](https://github.com/RadxaOS-SDK/rsdk/actions/workflows/docs.yaml/badge.svg)](https://github.com/RadxaOS-SDK/rsdk/actions/workflows/docs.yaml) 4 | 5 | To learn more about `rsdk`, please visit [our documentation](https://RadxaOS-SDK.github.io/rsdk/). 6 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Radxa Limited"] 3 | language = "en" 4 | multilingual = true 5 | src = "docs" 6 | title = "rsdk" 7 | 8 | [build] 9 | extra-watch-dirs = ["po"] 10 | 11 | [output.linkcheck] 12 | 13 | [output.html] 14 | git-repository-url = "https://github.com/RadxaOS-SDK/rsdk/tree/main" 15 | edit-url-template = "https://github.com/RadxaOS-SDK/rsdk/edit/main/{path}" 16 | additional-css = [ 17 | "./theme/css/mdbook-admonish.css", 18 | "./theme/css/language-picker.css", 19 | ] 20 | 21 | [preprocessor.admonish] 22 | command = "mdbook-admonish" 23 | assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install` 24 | 25 | [preprocessor.gettext] 26 | after = ["links"] 27 | 28 | [preprocessor.toc] 29 | command = "mdbook-toc" 30 | renderer = ["html"] 31 | 32 | [preprocessor.cmdrun] 33 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | /.debhelper 2 | /debhelper-build-stamp 3 | /files 4 | /rsdk*/ 5 | /*.debhelper.log 6 | /*.postrm.debhelper 7 | /*.substvars 8 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: rsdk 2 | Maintainer: "Radxa Computer Co., Ltd" 3 | Section: admin 4 | Priority: standard 5 | Standards-Version: 4.6.0 6 | Build-Depends: debhelper (>=12~), 7 | devscripts, 8 | lintian, 9 | dh-exec, 10 | pandoc, 11 | shellcheck, 12 | 13 | Package: rsdk 14 | Architecture: all 15 | Section: admin 16 | Priority: standard 17 | Depends: apt-utils, 18 | bash-completion, 19 | bdebstrap, 20 | binfmt-support, 21 | curl, 22 | debian-archive-keyring, 23 | debian-ports-archive-keyring, 24 | dosfstools, 25 | gdisk, 26 | jsonnet, 27 | jq, 28 | libguestfs-tools, 29 | librtui, 30 | parted, 31 | qemu-user-static, 32 | radxa-archive-keyring, 33 | wget, 34 | xz-utils, 35 | ${misc:Depends}, 36 | Recommends: git, 37 | gh, 38 | ubuntu-keyring, 39 | vscodium-archive-keyring, 40 | Description: RadxaOS Software Development Kit 41 | RadxaOS Software Development Kit (rsdk) provides the managed environment to 42 | build system images and essential packages. 43 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: rsdk 3 | Source: https://github.com/RadxaOS-SDK/rsdk 4 | 5 | Files: * 6 | Copyright: © 2024 Radxa Computer Co., Ltd 7 | License: GPL-3+ 8 | 9 | License: GPL-3+ 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 3, or (at your option) 13 | any later version. 14 | . 15 | This program is distributed in the hope that it will be useful, but 16 | WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | General Public License for more details. 19 | . 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 23 | 02110-1301, USA. 24 | . 25 | On Debian systems, the complete text of the GNU General Public License 26 | can be found in /usr/share/common-licenses/GPL-3. 27 | -------------------------------------------------------------------------------- /debian/rsdk.docs: -------------------------------------------------------------------------------- 1 | src/SOURCE 2 | -------------------------------------------------------------------------------- /debian/rsdk.install: -------------------------------------------------------------------------------- 1 | src/bin/ /usr/ 2 | src/lib/ /usr/ 3 | src/libexec/ /usr/ 4 | src/share/bash-completion/ /usr/share/ 5 | src/share/rsdk/ /usr/share/ 6 | src/share/man/man8/*.8 /usr/share/man/man8/ 7 | -------------------------------------------------------------------------------- /debian/rsdk.lintian-overrides: -------------------------------------------------------------------------------- 1 | # Small bug number is very probable for us. 2 | rsdk: improbable-bug-number-in-closes 3 | 4 | # src/share/rsdk/infra-package/debian/rules have shebang. 5 | # However, this file is only for the template and will not actually run. 6 | rsdk: missing-dep-for-interpreter 7 | 8 | # src/share/rsdk/infra-package/ have .gitignore 9 | # However, this file is only for the template. 10 | rsdk: package-contains-vcs-control-file 11 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | include /usr/share/dpkg/pkg-info.mk 4 | include /usr/share/dpkg/architecture.mk 5 | 6 | %: 7 | dh $@ 8 | 9 | override_dh_builddeb: 10 | dh_builddeb -- -Zxz 11 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /debian/source/lintian-overrides: -------------------------------------------------------------------------------- 1 | # Our package is built on GitHub-hosted runner, 2 | # which uses Ubuntu, and will default to zstd compression. 3 | # This is currently not supported in Debian. 4 | rsdk source: custom-compression-in-debian-rules 5 | -------------------------------------------------------------------------------- /debs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /devenv.local.nix.example: -------------------------------------------------------------------------------- 1 | # You can use devenv.local.nix to override the default settings. 2 | # This file is provided as an example. 3 | 4 | { pkgs, ... }: 5 | 6 | { 7 | # Override rsdk defaults here 8 | env = { 9 | RSDK_OPTION_REPO_SUFFIX = "-test"; 10 | RSDK_OPTION_DISTRO_MIRROR = "http://apt.vamrs.org"; 11 | RSDK_OPTION_RADXA_MIRROR = "http://apt.vamrs.org/rbuild-"; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /devenv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devenv": { 4 | "locked": { 5 | "dir": "src/modules", 6 | "lastModified": 1735530587, 7 | "owner": "cachix", 8 | "repo": "devenv", 9 | "rev": "69645885c1052cc1ca398ac30ba7dfc63386c0e3", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "dir": "src/modules", 14 | "owner": "cachix", 15 | "repo": "devenv", 16 | "type": "github" 17 | } 18 | }, 19 | "flake-compat": { 20 | "flake": false, 21 | "locked": { 22 | "lastModified": 1733328505, 23 | "owner": "edolstra", 24 | "repo": "flake-compat", 25 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "edolstra", 30 | "repo": "flake-compat", 31 | "type": "github" 32 | } 33 | }, 34 | "git-hooks": { 35 | "inputs": { 36 | "flake-compat": "flake-compat", 37 | "gitignore": "gitignore", 38 | "nixpkgs": [ 39 | "nixpkgs" 40 | ] 41 | }, 42 | "locked": { 43 | "lastModified": 1742649964, 44 | "owner": "cachix", 45 | "repo": "git-hooks.nix", 46 | "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "cachix", 51 | "repo": "git-hooks.nix", 52 | "type": "github" 53 | } 54 | }, 55 | "gitignore": { 56 | "inputs": { 57 | "nixpkgs": [ 58 | "git-hooks", 59 | "nixpkgs" 60 | ] 61 | }, 62 | "locked": { 63 | "lastModified": 1709087332, 64 | "owner": "hercules-ci", 65 | "repo": "gitignore.nix", 66 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 67 | "type": "github" 68 | }, 69 | "original": { 70 | "owner": "hercules-ci", 71 | "repo": "gitignore.nix", 72 | "type": "github" 73 | } 74 | }, 75 | "nixpkgs": { 76 | "locked": { 77 | "lastModified": 1735523292, 78 | "owner": "NixOS", 79 | "repo": "nixpkgs", 80 | "rev": "6d97d419e5a9b36e6293887a89a078cf85f5a61b", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "NixOS", 85 | "ref": "nixpkgs-unstable", 86 | "repo": "nixpkgs", 87 | "type": "github" 88 | } 89 | }, 90 | "root": { 91 | "inputs": { 92 | "devenv": "devenv", 93 | "git-hooks": "git-hooks", 94 | "nixpkgs": "nixpkgs", 95 | "pre-commit-hooks": [ 96 | "git-hooks" 97 | ] 98 | } 99 | } 100 | }, 101 | "root": "root", 102 | "version": 7 103 | } 104 | -------------------------------------------------------------------------------- /devenv.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | 3 | { 4 | # https://devenv.sh/packages/ 5 | packages = with pkgs; [ 6 | aptly 7 | bash-completion 8 | cargo 9 | commitizen 10 | curl 11 | dosfstools 12 | file 13 | git 14 | gh 15 | gptfdisk 16 | guestfs-tools 17 | jq 18 | libguestfs-with-appliance 19 | mdbook 20 | mdbook-admonish 21 | mdbook-cmdrun 22 | mdbook-i18n-helpers 23 | mdbook-linkcheck 24 | mdbook-toc 25 | multipath-tools 26 | newt 27 | parted 28 | util-linux 29 | wget 30 | xz 31 | yq 32 | zx 33 | ]; 34 | 35 | enterShell = '' 36 | export PATH=$PWD/src/bin:$PWD/node_modules/.bin:$HOME/.cargo/bin:$PATH 37 | 38 | if [[ -n "$DEVENV_NIX" ]] 39 | then 40 | # Does not work from direnv 41 | # https://github.com/direnv/direnv/issues/773#issuecomment-792688396 42 | source $PWD/src/share/bash-completion/completions/rsdk 43 | rsdk welcome 44 | else 45 | rsdk welcome 'Please run `rsdk shell` to enter the full development shell. 46 | ' 47 | fi 48 | ''; 49 | 50 | languages.javascript = { 51 | enable = true; 52 | npm.enable = true; 53 | }; 54 | languages.jsonnet.enable = true; 55 | 56 | pre-commit = { 57 | hooks = { 58 | commitizen.enable = true; 59 | shellcheck = { 60 | enable = true; 61 | entry = lib.mkForce "${pkgs.shellcheck}/bin/shellcheck -x"; 62 | }; 63 | shfmt.enable = true; 64 | statix.enable = true; 65 | typos = { 66 | enable = true; 67 | excludes = [ 68 | "theme/highlight.js" 69 | ]; 70 | settings.ignored-words = [ 71 | "Synopsys" 72 | "HSI" 73 | ]; 74 | }; 75 | }; 76 | }; 77 | 78 | starship.enable = true; 79 | } 80 | -------------------------------------------------------------------------------- /devenv.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | nixpkgs: 3 | url: github:NixOS/nixpkgs/nixpkgs-unstable 4 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](intro.md) 4 | - [Why rsdk?](why.md) 5 | 6 | # Installation 7 | 8 | - [With Visual Studio Code & devcontainer](install/vscode.md) 9 | - [With devcontainer alone](install/devcontainer.md) 10 | - [Using released Debian package](install/deb.md) 11 | - [Native installation](install/native.md) 12 | 13 | # Tutorials 14 | 15 | - [Basic usage](tutorials/usage.md) 16 | - [Migrating from old toolchain](tutorials/migration.md) 17 | - [Build customization](tutorials/customize.md) 18 | - [Adding support for new device](tutorials/new_device.md) 19 | - [Global build options](tutorials/global_options.md) 20 | - [Work with local packages](tutorials/local_pkg.md) 21 | 22 | # Command References 23 | 24 | - [rsdk](cmd/rsdk.md) 25 | - [rsdk-build](cmd/rsdk-build.md) 26 | - [rsdk-chroot](cmd/rsdk-chroot.md) 27 | - [rsdk-install](cmd/rsdk-install.md) 28 | - [rsdk-shell](cmd/rsdk-shell.md) 29 | -------------------------------------------------------------------------------- /docs/cmd/rsdk-build.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Build RadxaOS image 4 | 5 | When no suite or edition options is supplied, `rsdk-build` will use the product-specific default values, which are defined in `src/share/rsdk/configs/products.json` as the first element of the respective array. 6 | Using ROCK 3C as an example, if you want to build a CLI image for RadxaOS Bullseye, you can run the following command: 7 | 8 | ```bash 9 | rsdk build rock-3c bullseye cli 10 | ``` 11 | 12 | ## RadxaOS output path 13 | 14 | you can find the generated RadxaOS image as `out/${product}_${suite}_${edition}/output.img`. 15 | -------------------------------------------------------------------------------- /docs/cmd/rsdk-chroot.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/cmd/rsdk-install.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/cmd/rsdk-shell.md: -------------------------------------------------------------------------------- 1 | # `rsdk-shell` 2 | 3 | It is recommended to run `rsdk shell` first to set up the work environment before running other commands. 4 | However, most commands should run without issue. 5 | Some enhancements (for example, bash completion and shell prompt) may not be available outside of `rsdk shell` by default. 6 | -------------------------------------------------------------------------------- /docs/cmd/rsdk.md: -------------------------------------------------------------------------------- 1 | # rsdk 2 | 3 | `rsdk` command is the common CLI entry point. 4 | 5 | When it is run without any argument, it will run `rsdk-tui` instead. 6 | -------------------------------------------------------------------------------- /docs/install/deb.md: -------------------------------------------------------------------------------- 1 | # Run `rsdk` using released Debian package 2 | 3 | To be released. 4 | -------------------------------------------------------------------------------- /docs/install/devcontainer.md: -------------------------------------------------------------------------------- 1 | # Run `rsdk` with devcontainer alone 2 | 3 | This is similar to how we build system images in the CI pipelines. 4 | 5 | First, please install the required dependencies: 6 | 7 | ```bash 8 | sudo apt-get update 9 | sudo apt-get install git qemu-user-static binfmt-support 10 | sudo apt-get install npm docker.io 11 | sudo usermod -a -G docker $USER 12 | ``` 13 | 14 | If you were not in the `docker` group before, you will need to log out and log back in. 15 | 16 | For SSH, simple disconnect the current session and reconnect. 17 | 18 | Then clone the project with `git` and install `devcontainer`: 19 | 20 | ```bash 21 | git clone --recurse-submodules https://github.com/RadxaOS-SDK/rsdk.git 22 | cd rsdk 23 | npm install @devcontainers/cli 24 | export PATH="$PWD/src/bin:$PWD/node_modules/.bin:$PATH" 25 | rsdk devcon up 26 | rsdk devcon 27 | ``` 28 | 29 | You are now inside the `rsdk`'s `devcontainer` shell. 30 | 31 | The following recording demostates how to set up `rsdk` and build an image on a fresh Debian 12 install: 32 | 33 | [![asciicast](https://asciinema.org/a/A064TrKbZsXncNkEveIUFAGvp.svg)](https://asciinema.org/a/A064TrKbZsXncNkEveIUFAGvp) 34 | 35 | ## Common issues 36 | 37 | 1. devcontainer setup paused with `You might be rate limited by GitHub.` message 38 | 39 | You might be rate limited by GitHub. Please follow the instruction listed in the output. 40 | 41 | 2. Failed to launch devcontainer. 42 | 43 | Please edit `.devcontainer/devcontainer.json`, and adjust `runArgs` property. 44 | -------------------------------------------------------------------------------- /docs/install/native.md: -------------------------------------------------------------------------------- 1 | # Run `rsdk` natively 2 | 3 | ```admonish warning 4 | This is not a well supported or tested installation method. 5 | 6 | When you have issues, please check the source code for up-to-date runtime dependencies. 7 | 8 | We do not answer support questions related to this type of installation. 9 | ``` 10 | 11 | To run `rsdk` natively, you will ideally need an Ubuntu system, as it is the base system used in Dev Container. 12 | 13 | Please first install [`devenv`](https://devenv.sh/getting-started/#2-install-cachix) on your system. 14 | 15 | Optionally you can setup [`direnv`](https://devenv.sh/automatic-shell-activation/), then run `direnv allow` within the project folder to enable it. 16 | 17 | You can then run `devenv shell` to enter the development shell. This shell will manipulate your PATH to have the development dependency available. 18 | 19 | If you have `direnv` setup, you don't have to run the above command when you enter the project directory to use the SDK. However, the `direnv` shell lacks `starship` integration as well as `rsdk` auto completion, as it only saves the environmental variables. 20 | 21 | There are some additional system configurations and packages that are currently not managed by `devenv`. They are mostly covered by `install_native_dependency` function in `rsdk-setup`. 22 | -------------------------------------------------------------------------------- /docs/install/vscode.md: -------------------------------------------------------------------------------- 1 | # Run `rsdk` with Visual Studio Code & devcontainer 2 | 3 | 4 | ```admonish info 5 | This is the preferred method to run `rsdk`. 6 | ``` 7 | 8 | First, please install the required dependencies: 9 | 10 | ```bash 11 | sudo apt-get update 12 | sudo apt-get install git qemu-user-static binfmt-support 13 | ``` 14 | 15 | Then follow Visual Studio Code's documentation to: 16 | 17 | 1. [Install Visual Studio Code](https://code.visualstudio.com/docs/setup/setup-overview) 18 | 2. [Setup devcontainer](https://code.visualstudio.com/docs/devcontainers/containers) 19 | 20 | Then clone the project with `git`: 21 | 22 | ```bash 23 | git clone --recurse-submodules https://github.com/RadxaOS-SDK/rsdk.git 24 | ``` 25 | 26 | Open the project in Visual Studio Code. A notification will pop up on the corner 27 | asking if you want to reopen in devcontainer. Click `yes` and wait for the container 28 | to be set up. 29 | 30 | This can be combined with VS Code remote development extension to run rsdk in other systems. 31 | 32 | ## Common issues 33 | 34 | 1. devcontainer setup paused with `You might be rate limited by GitHub.` message 35 | 36 | You might be rate limited by GitHub. Please follow the instruction listed in the output. 37 | 38 | 2. Failed to launch devcontainer. 39 | 40 | Please edit `.devcintainer/devcontainer.json`, and adjust `runArgs` property. 41 | -------------------------------------------------------------------------------- /docs/intro.md: -------------------------------------------------------------------------------- 1 | # `rsdk` 2 | 3 | `rsdk` is the latest system development kit from Radxa. 4 | 5 | It is built upon our previous experiences with [`rbuild`](https://github.com/radxa-repo/rbuild) 6 | and [`debos-radxa`](https://github.com/radxa/debos-radxa), while also adds many other utilities 7 | to improve the developer / maintainer experience. 8 | -------------------------------------------------------------------------------- /docs/tutorials/customize.md: -------------------------------------------------------------------------------- 1 | # Build customization 2 | 3 | `rsdk` uses [`devenv`](https://devenv.sh/) to manage its **dev**elopment **env**rionronment, but itself is not `nix` based. `nix` has good support generating `NixOS` images, but here we are dealing with a Debian system, and some parts are [currently missing](https://github.com/NixOS/nixpkgs/pull/270095). 4 | 5 | We currently uses [`bdebstrap`](https://github.com/bdrung/bdebstrap), which is a YAML frontend for [`mmdebstrap`](https://gitlab.mister-muffin.de/josch/mmdebstrap). `mmdebstrap` is [the recommended tool](https://wiki.debian.org/RISC-V#Creating_a_riscv64_chroot) for building RISC-V systems compared to traditional `debootstrap`. 6 | 7 | YAML itself is not a templating language, so it cannot dynamically generate different configurations for different builds. We use [`jsonnet`](https://jsonnet.org) for this purpose. 8 | 9 | Lastly, `mmdebstrap` does not handle disk image generation. We again use `jsonnet` to dynamically generate a [`guestfish`](https://libguestfs.org/guestfish.1.html) script to handle this task. 10 | 11 | All of those tools are glued by `bash` to provide a frontend, known as [`rsdk-build`](https://github.com/RadxaOS-SDK/rsdk/tree/main/src/libexec/rsdk/rsdk-build). 12 | 13 | Depending on your goal, you would need the knowledge of some of the above tools. 14 | 15 | ## Rootfs customization 16 | 17 | [`rootfs.jsonnet`](https://github.com/RadxaOS-SDK/rsdk/tree/main/src/share/rsdk/build/rootfs.jsonnet) is the entry point for rootfs template. It collects the various inputs and passes them to different modules. 18 | 19 | Module loading order matters, as that will determine [`*-hooks`](https://manpages.debian.org/testing/mmdebstrap/mmdebstrap.1.en.html#HOOKS)'s execution order. The safest way is to only edit the `customize-hooks` field in `rootfs.jsonnet` and only adding new entries after the existing ones. 20 | 21 | You can also edit the `packages` field in `rootfs.jsonnet` to add additional packages to the system. `customize-hooks` will be run after `packages` are installed in the rootfs. 22 | 23 | Checkout [`Work with local packages`](local_pkg.md#rsdk-build---debs) if you have local packages to install. 24 | 25 | ## Disk image customization 26 | 27 | [`image.jsonnet`](https://github.com/RadxaOS-SDK/rsdk/tree/main/src/share/rsdk/build/rootfs.jsonnet) is the template for the deployment script. It is generally not necessary to change this part. 28 | -------------------------------------------------------------------------------- /docs/tutorials/global_options.md: -------------------------------------------------------------------------------- 1 | # Global build options 2 | 3 | Like [`rbuild`](https://radxa-repo.github.io/rbuild/dev/config.html), `rsdk` also 4 | allows defining global build options. The underlying mechanical is the same: 5 | predefined environmental variables. However, since we use `devenv` to manage the 6 | environment, the way to define them is also changed. 7 | 8 | For now, you will need to add your definitions in `devenv.local.nix` file. We 9 | provide `devenv.local.nix.example` as a reference for file structure. This is also 10 | what we use in the office, but the server is locally hosted, so you won't be 11 | able to use it. 12 | 13 | ## Example: set up local apt cache to speed up build 14 | 15 | If you want to speed up image building time, one way is to use a locally hosted 16 | apt cache to reduce download time. 17 | 18 | First, copy `devenv.local.nix.example` to `devenv.local.nix`. You can then remove 19 | `RSDK_OPTION_REPO_SUFFIX` if you do not want to build test image by default, and 20 | then change `RSDK_OPTION_*_MIRROR` to your own address. 21 | 22 | Below are example NixOS configuration to set up a local apt cache service, as 23 | well as the mirror definition for `acng.conf` file. They may not be complete, so 24 | adjust to match your own use case. 25 | 26 | ```nix 27 | { 28 | virtualisation = { 29 | oci-containers = { 30 | backend = "podman"; 31 | containers = { 32 | acng = { 33 | image = "docker.io/mbentley/apt-cacher-ng"; 34 | ports = [ 35 | "3142:3142" 36 | ]; 37 | volumes = [ 38 | "/home/acng/containers/acng.conf:/etc/apt-cacher-ng/acng.conf" 39 | "/home/acng/containers/acng/:/var/cache/apt-cacher-ng/" 40 | ]; 41 | environment = { 42 | PUID = "1000"; 43 | PGID = "100"; 44 | TZ = "Asia/Shanghai"; 45 | }; 46 | }; 47 | }; 48 | }; 49 | }; 50 | } 51 | ``` 52 | 53 | ``` 54 | Remap-debian: /debian ; http://mirrors.tuna.tsinghua.edu.cn/debian 55 | Remap-debian-security: /debian-security ; http://mirrors.tuna.tsinghua.edu.cn/debian-security 56 | Remap-ubuntu: /ubuntu ; http://mirrors.tuna.tsinghua.edu.cn/ubuntu 57 | Remap-ubuntu-ports: /ubuntu-ports ; http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports 58 | Remap-armbian: /armbian ; http://mirrors.tuna.tsinghua.edu.cn/armbian 59 | Remap-proxmox: /proxmox ; http://mirrors.tuna.tsinghua.edu.cn/proxmox/debian 60 | Remap-proxmox-new: /debian/pve ; http://mirrors.tuna.tsinghua.edu.cn/proxmox/debian/pve 61 | Remap-rbuild: /rbuild ; http://radxa-repo.github.io/apt 62 | Remap-rbuild-buster: /rbuild-buster ; http://radxa-repo.github.io/buster 63 | Remap-rbuild-buster-test: /rbuild-buster-test ; http://radxa-repo.github.io/buster-test 64 | Remap-rbuild-bullseye: /rbuild-bullseye ; http://radxa-repo.github.io/bullseye 65 | Remap-rbuild-bullseye-test: /rbuild-bullseye-test ; http://radxa-repo.github.io/bullseye-test 66 | Remap-rbuild-rk3528a-bullseye-test: /rbuild-rk3528a-bullseye-test ; http://radxa-repo.github.io/rk3528a-bullseye-test 67 | Remap-rbuild-focal: /rbuild-focal ; http://radxa-repo.github.io/focal 68 | Remap-rbuild-focal-test: /rbuild-focal-test ; http://radxa-repo.github.io/focal-test 69 | Remap-rbuild-jammy: /rbuild-jammy ; http://radxa-repo.github.io/jammy 70 | Remap-rbuild-jammy-test: /rbuild-jammy-test ; http://radxa-repo.github.io/jammy-test 71 | Remap-rbuild-bookworm: /rbuild-bookworm ; http://radxa-repo.github.io/bookworm 72 | Remap-rbuild-bookworm-test: /rbuild-bookworm-test ; http://radxa-repo.github.io/bookworm-test 73 | Remap-rbuild-rk3588-bookworm-test: /rbuild-rk3588-bookworm-test ; http://radxa-repo.github.io/rk3588-bookworm-test 74 | Remap-rbuild-rk3588s2-bookworm-test: /rbuild-rk3588s2-bookworm-test ; http://radxa-repo.github.io/rk3588s2-bookworm-test 75 | Remap-rbuild-sid: /rbuild-sid ; http://radxa-repo.github.io/sid 76 | Remap-rbuild-sid-test: /rbuild-sid-test ; http://radxa-repo.github.io/sid-test 77 | Remap-rbuild-noble-test: /rbuild-noble-test ; http://radxa-repo.github.io/noble-test 78 | Remap-rbuild-vscodium: /rbuild-debs ; https://paulcarroty.gitlab.io/vscodium-deb-rpm-repo/debs 79 | ``` 80 | -------------------------------------------------------------------------------- /docs/tutorials/local_pkg.md: -------------------------------------------------------------------------------- 1 | # Work with local packages 2 | 3 | ## Background 4 | 5 | When working at the bleeding edge, developer needs to test some locally built 6 | packages before committing the changes. However, to ensure the build is reproducible, 7 | maintainer wants to lock up all inputs, usually in a version-controlled way. 8 | 9 | At Radxa, this conflict primarily impacts our BSP developers, who are not involved 10 | in toolchain development. As such, `rbuild` provides 11 | [some helper flags](https://radxa-repo.github.io/rbuild/dev/bsp.html) to allow 12 | better integration with `bsp`'s build outputs. The scope of local packages is 13 | intentionally limited to kernel and firmware packages, since the development 14 | workflow for the OS maintainers is different: just test the package on a live system. 15 | 16 | `rsdk` initially dropped this support. As an evolution of `rbuild`, the 17 | package situation was stable enough that BSP developers did not need to build 18 | images with custom packages very often. The support is now available in more 19 | general form, in hope to support fully offline system building in the future. 20 | 21 | ## `rsdk-build --debs` 22 | 23 | `rsdk-build` now supports `--debs ` flag. A folder containing locally 24 | built packages are needed with this flag. 25 | 26 | When this flag is specified, the content of `debs_dir` will be copied inside the 27 | target system, and will be added as a local apt repository under `/srv/local-apt-repository`, 28 | and it will have pin priority of 1999, effecitive making it the only provider of the included package. 29 | 30 | ```admonish warning 31 | Unlike `rbuild`, this local apt repository will persist in the rootfs. This will 32 | block future package upgrade via `apt` if it is available in an online source, 33 | and also serves as the build input for future reproduceible build. 34 | 35 | Consider clear `/srv/local-apt-repository` after the build if this behaviour is 36 | undesired. 37 | ``` 38 | 39 | When running `rsdk` in `devcontainer`, we recommend `debs_dir` to be inside `rsdk` 40 | project folder (for example, the `debs` folder in the project root). As the host 41 | path may not be mapped inside `devcontainer`, `rsdk-build` may not be able to 42 | access it. 43 | 44 | ## Add packages that are not part of the default install 45 | 46 | Because the package are not explicitly installed like the case of `rbuild`, if 47 | you want a package to be installed, it has to also be installed by the normal build 48 | steps. 49 | 50 | If your package is not installed by default, you will need to follow [`Rootfs customization`](customize.md#rootfs-customization) 51 | to add them to the build steps. 52 | 53 | ## Override packages that are part of the default install 54 | 55 | For example, if we want to replace the U-Boot for ROCK 4SE, we need to provide 56 | both the `u-boot-rock-4se` metapackage, which is [installed by the build script](https://github.com/RadxaOS-SDK/rsdk/blob/47a766e773b187543dd5f38f7fc8c0df7d49e8b0/src/share/rsdk/build/mod/packages/categories/core.libjsonnet#L81), 57 | and the `u-boot-latest` binary package, which provides the bootloader and is 58 | `u-boot-rock-4se`'s dependency. 59 | 60 | Usually you should copy every generated packages to `debs_dir` for each project 61 | you are going to override. This is to reduce the likelihood of missing a dependency. 62 | -------------------------------------------------------------------------------- /docs/tutorials/migration.md: -------------------------------------------------------------------------------- 1 | # Migrating from old toolchain 2 | 3 | ## `rbuild` 4 | 5 | `rsdk build` is the `rbuild` replacement. 6 | It uses the same argument ordering, and support similar input values. 7 | 8 | When no suite or edition is supplied, `rsdk build` will use the value defined in `src/share/rsdk/configs/products.json` instead of `bullseye` `cli`. 9 | 10 | Not all `rbuild` options are supported by `rsdk build`. 11 | Please check the command help for more details. 12 | 13 | `.rbuild-config` file is now replaced by [`devenv.local.nix`](global_options.md), and option names are adjusted. 14 | You can check `devenv.local.nix.example` for syntax. 15 | 16 | ### `rbuild json` 17 | 18 | This subcommand is replaced by configuration files under `src/share/rsdk/configs`. 19 | 20 | ### `rbuild shrink-image` 21 | 22 | This subcommand is no longer needed, as now image shrinking is no longer a root operation, and comes standard. 23 | 24 | ### `rbuild write-image` 25 | 26 | `rsdk write-image` is the `rbuild write-image` replacement. 27 | It uses the same argument ordering. 28 | -------------------------------------------------------------------------------- /docs/tutorials/new_device.md: -------------------------------------------------------------------------------- 1 | # Adding support for new device 2 | 3 | Every device supported by RadxaOS requires several metapackages available in the 4 | apt repositories. They are usually unique to each hardware, as such cannot be 5 | shared between devices. 6 | 7 | It is intentional to keep this info in form of package dependencies, and spread 8 | out in several packages, instead of a single hard coded config file. This is because: 9 | 10 | 1. Different build tools don't need to track this config in order to build with 11 | correct packages. 12 | 2. Ease of migration between tools. 13 | For example, from `rbuild` to `rsdk`, we use the same simple package logic 14 | instead doing data transform, which was the case for `rbuild`'s `configs` 15 | files. 16 | 3. Allow underlying package to be changed/updated in the future. 17 | 18 | ## Adding new device 19 | 20 | Currently, there are 4 places that need to be updated: 21 | 22 | 1. Kernel metapackages 23 | Those includes Linux kernel image as well as kernel header, and some other 24 | less used packages. 25 | Currently you need to edit the related `bsp` 26 | [Linux profile](https://github.com/radxa-repo/bsp/blob/main/linux/latest/fork.conf) 27 | to include the new device. 28 | 2. Firmware metapackage 29 | This is similar to the kernel package in case of U-Boot, where the 30 | [U-Boot profile](https://github.com/radxa-repo/bsp/blob/main/u-boot/latest/fork.conf) 31 | needs to be updated. 32 | For EDK2 you will need to [add the metapackage](https://github.com/radxa-pkg/edk2-cix/blob/main/debian/control) 33 | in the related repo. 34 | 3. Product metapackage 35 | Each product also needs its own package to pull device-specific drivers, and 36 | some common config options. 37 | Those are defined in [`radxa-profiles`](https://github.com/radxa-pkg/radxa-profiles/blob/main/debian/control) 38 | repo. 39 | 4. [`products.json`](https://github.com/RadxaOS-SDK/rsdk/blob/main/src/share/rsdk/configs/products.json) 40 | This registers the supported products for `rsdk` and their default configurations. 41 | 42 | Right now, product metapackage does not specify dependencies to kernel and 43 | firmware (even though we have product-agnostic metapackages for those two). This 44 | is to allow users to install custom kernels only without breaking the 45 | dependencies. 46 | 47 | Note that vendor metapackage is listed as recommended in product metapackages. 48 | This way users can install the system without SoC vendors' binary packages. 49 | 50 | Finally, create the new product build repo under [`radxa-build`](https://github.com/radxa-build) 51 | with `rsdk-infra-product-update` command. 52 | 53 | ## What if we introduce a new SoC? 54 | 55 | You need to additionally update following places: 56 | 57 | 1. Vendor metapackage 58 | Each SoC needs their own package to pull SoC-specific packages, and 59 | some common config options. 60 | Those are defined in [`vendor-profiles`](https://github.com/radxa-pkg/vendor-profiles/blob/main/debian/control) 61 | repo. 62 | 2. [`socs.json`](https://github.com/RadxaOS-SDK/rsdk/blob/main/src/share/rsdk/configs/socs.json) 63 | New SoC **MUST** be added to `soc_specific_repo` array as well. 64 | 3. New SoC-specific apt repo under [`radxa-repo`](https://github.com/radxa-repo) organization. 65 | 4. SoC-specific package repo 66 | In case of Rockchip, those are managed by [`rockchip-prebuilt`](https://github.com/radxa-pkg/rockchip-prebuilt) 67 | repo, and we create Rockchip SDK prebuilt packages in GitHub Releases, which 68 | will be uploaded to the SoC-specific apt repo. 69 | If the new SoC is only a variant of already supported SoC, then you only need 70 | to edit the related [`pkg.conf`](https://github.com/radxa-pkg/rockchip-prebuilt/blob/main/pkg.conf.linux-6.1-stan-rkr1) 71 | to include the new SoC-specific apt repo. 72 | 73 | ## What if we introduce a new SoC vendor? 74 | 75 | You need to additionally update following places: 76 | 77 | 1. Vendor metapackage 78 | Each vendor needs their own package to pull common config options. 79 | Those are defined in [`vendor-profiles`](https://github.com/radxa-pkg/vendor-profiles/blob/main/debian/control) 80 | repo. 81 | 2. [`socs.json`](https://github.com/RadxaOS-SDK/rsdk/blob/main/src/share/rsdk/configs/socs.json) 82 | There should be a new item for the new vendor. 83 | -------------------------------------------------------------------------------- /docs/tutorials/usage.md: -------------------------------------------------------------------------------- 1 | # Basic usage 2 | 3 | `rsdk` comes with `bash-completion` to assist its CLI usage. 4 | 5 | After typing `rsdk` into your terminal, if there is no subcommand suggestion after you press Tab key twice, you should run `rsdk shell` to enter the development environment. 6 | 7 | From there, you can use autocompletion to query the supported command list. 8 | 9 | Running a command with `--help` argument will display its help text. 10 | 11 | ## Use TUI to run guided tasks 12 | 13 | `rsdk` command is the common CLI entry point. 14 | 15 | When it is run without any argument, `rsdk-tui` will be run instead. 16 | 17 | 1. Start TUI Wizard by running `rsdk` in the terminal. 18 | 19 | 2. Select the task you want to run. 20 | You can use arrow key to navigate, use Enter key to select, and use Escape key to leave current window. 21 | In this example, we will choose `Build system image`: 22 | 23 | ```bash 24 | ┌─────────────────┤ RSDK ├──────────────────┐ 25 | │ Please select a task: │ 26 | │ │ 27 | │ Build system image │ 28 | │ ========= │ 29 | │ About │ 30 | │ │ 31 | │ │ 32 | │ │ 33 | └───────────────────────────────────────────┘ 34 | ``` 35 | 36 | 3. Select the product you want to build. 37 | You can use the space bar to select the product, and the chosen product will have asterisk symbol placed in the parentheses. 38 | **Enter key does not select the product when used alone!** 39 | In this example, we will choose `rock-5b-6_1`: 40 | 41 | ```bash 42 | ┌─────────────────┤ RSDK ├──────────────────┐ 43 | │ Please select a product: │ 44 | │ │ 45 | │ ( ) radxa-e25 ▒ │ 46 | │ (*) rock-5b-6_1 ▒ │ 47 | │ ( ) rock-5b ▒ │ 48 | │ │ 49 | │ │ 50 | │ │ 51 | └───────────────────────────────────────────┘ 52 | ``` 53 | 54 | 4. Select `Yes` to start the build process. 55 | `rsdk-tui` will then run the associated CLI commands to complete the task: 56 | 57 | ```bash 58 | ┌─────────────────┤ RSDK ├──────────────────┐ 59 | │ │ 60 | │ Are you sure to build for 'rock-5b-6_1'? │ 61 | │ │ 62 | │ │ 63 | │ │ 64 | │ │ 65 | └───────────────────────────────────────────┘ 66 | ``` 67 | 68 | Advanced build should use [`rsdk-build`](../cmd/rsdk-build.md) command instead. -------------------------------------------------------------------------------- /docs/why.md: -------------------------------------------------------------------------------- 1 | # Why another system builder? 2 | 3 | `rsdk` is yet another evolution of Radxa's system builder. The primary goal is to 4 | move away from [`debos`](https://github.com/go-debos/debos) for following reasons: 5 | 6 | 1. (Previously) [Lack of ARM64 support](https://github.com/go-debos/debos/issues/363). 7 | 2. We use pagefile to workaround dkms build failure, which [requires KVM to be available](https://github.com/radxa-repo/rbuild/issues/16#issuecomment-1534176754). 8 | 3. Go templates leave much to be desired. 9 | 4. [Provided actions](https://pkg.go.dev/github.com/go-debos/debos/actions) are becoming limiting to achieve our desired result. 10 | 11 | Beyond those, our system has grown into 100+ repositories, interconnected by various CI/CD workflows. 12 | From an operational standpoint we also need a tool to centrally manage them, with the added bonus that 13 | customers can use the very same tool to reproduce our setup for their own use. 14 | 15 | Finally, we want to have a short answer to the commonly asked question "where can I download the SDK for X". 16 | So far, our answer has always been a brief explanation of the system design, because of its complexity. 17 | We want to have something that matches customer's expectation more closely, where there is only a single 18 | entry to all related Radxa source code. 19 | 20 | Thus, `rsdk` is born. 21 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rsdk", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "@devcontainers/cli": "^0.72.0" 9 | } 10 | }, 11 | "node_modules/@devcontainers/cli": { 12 | "version": "0.72.0", 13 | "resolved": "https://registry.npmjs.org/@devcontainers/cli/-/cli-0.72.0.tgz", 14 | "integrity": "sha512-vDv33/I5POw1wDJmcMbOCTWd3xTk4bbVruJ9Qgr5eiLSl1OsfufN5WfeTZqgK1HeqrNqtH/xPyCKB2LXDNIv3w==", 15 | "license": "MIT", 16 | "bin": { 17 | "devcontainer": "devcontainer.js" 18 | }, 19 | "engines": { 20 | "node": "^16.13.0 || >=18.0.0" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@devcontainers/cli": "^0.72.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /po/.gitignore: -------------------------------------------------------------------------------- 1 | /*.po~ 2 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | /SOURCE 2 | -------------------------------------------------------------------------------- /src/bin/rsdk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR 5 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 6 | # shellcheck source=src/lib/rsdk/utils.sh 7 | source "$SCRIPT_DIR/../lib/rsdk/utils.sh" 8 | 9 | local SUBCOMMAND="${1:-tui}" 10 | shift || true 11 | 12 | if [[ -e "$SCRIPT_DIR/../libexec/rsdk/rsdk-$SUBCOMMAND" ]]; then 13 | "$SCRIPT_DIR/../libexec/rsdk/rsdk-$SUBCOMMAND" "$@" 14 | else 15 | error "$EXIT_MISSING_SUBCOMMAND" "$SUBCOMMAND" 16 | fi 17 | } 18 | 19 | main "$@" 20 | -------------------------------------------------------------------------------- /src/lib/rsdk/stdlib.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | printf_array() { 4 | local FORMAT="$1" 5 | shift 6 | local ARRAY=("$@") 7 | 8 | if [[ $FORMAT == "json" ]]; then 9 | jq --compact-output --null-input '$ARGS.positional' --args -- "${ARRAY[@]}" 10 | else 11 | for i in "${ARRAY[@]}"; do 12 | # shellcheck disable=SC2059 13 | printf "$FORMAT" "$i" 14 | done 15 | fi 16 | } 17 | 18 | in_array() { 19 | local item="$1" 20 | shift 21 | [[ $* =~ $item ]] 22 | } 23 | 24 | array_intersect() { 25 | local a=() b=() 26 | while [[ $1 != "--" ]]; do 27 | a+=("$1") 28 | shift 29 | done 30 | shift 31 | b=("$@") 32 | 33 | local i j 34 | for i in "${a[@]}"; do 35 | for j in "${b[@]}"; do 36 | if [[ $i == "$j" ]]; then 37 | echo "$i" 38 | fi 39 | done 40 | done 41 | } 42 | 43 | array_remove() { 44 | local array_name="$1" item="$2" old_array=() new_array=() 45 | eval "old_array=( \"\${${array_name}[@]}\" )" 46 | for i in "${!old_array[@]}"; do 47 | if [[ $item != "${old_array[i]}" ]]; then 48 | new_array+=("${old_array[i]}") 49 | fi 50 | done 51 | eval "$array_name=( \"\${new_array[@]}\" )" 52 | } 53 | 54 | request_parallel() { 55 | local nproc 56 | nproc=$(($(nproc))) 57 | 58 | while (($(jobs -r | wc -l) > nproc)); do 59 | sleep 0.1 60 | done 61 | } 62 | 63 | wait_parallel() { 64 | # An error aware wait 65 | # Subshell inherits set -e so they will report error code correctly 66 | # https://stackoverflow.com/a/43776775 67 | while true; do 68 | wait -n || { 69 | local code="$?" 70 | ([[ $code == "127" ]] && exit 0 || exit "$code") 71 | break 72 | } 73 | done 74 | } 75 | -------------------------------------------------------------------------------- /src/lib/rsdk/utils.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | set -euo pipefail 4 | shopt -s nullglob 5 | 6 | LC_ALL="C" 7 | LANG="C.UTF-8" 8 | LANGUAGE="C.UTF-8" 9 | 10 | EXIT_SUCCESS=0 11 | EXIT_UNKNOWN_OPTION=1 12 | EXIT_TOO_FEW_ARGUMENTS=2 13 | EXIT_UNSUPPORTED_OPTION=3 14 | EXIT_SUDO_PERMISSION=4 15 | EXIT_BLKDEV_NO_ROOTDEV=5 16 | EXIT_DEV_SHM_TOO_SMALL=6 17 | EXIT_RUNNING_AS_ROOT=7 18 | EXIT_MISSING_SUBCOMMAND=8 19 | EXIT_FILE_NOT_EXIST=9 20 | EXIT_AUTHENTICATION_FAILED=10 21 | EXIT_NOT_BLOCK_DEVICE=11 22 | EXIT_RUNNING_IN_CONTAINER=12 23 | 24 | error() { 25 | case "$1" in 26 | "$EXIT_SUCCESS") ;; 27 | "$EXIT_UNKNOWN_OPTION") 28 | echo "Unknown option: '$2'." >&2 29 | ;; 30 | "$EXIT_TOO_FEW_ARGUMENTS") 31 | echo "Too few arguments." >&2 32 | ;; 33 | "$EXIT_UNSUPPORTED_OPTION") 34 | echo "Option '$2' is not supported." >&2 35 | ;; 36 | "$EXIT_SUDO_PERMISSION") 37 | echo "'$2' requires either passwordless sudo, or running in an interactive shell." >&2 38 | ;; 39 | "$EXIT_BLKDEV_NO_ROOTDEV") 40 | echo "Unable to find root partition for '$2'." >&2 41 | ;; 42 | "$EXIT_DEV_SHM_TOO_SMALL") 43 | echo "Your /dev/shm is too small. Current '$2', require '$3'." >&2 44 | ;; 45 | "$EXIT_RUNNING_AS_ROOT") 46 | cat <&2 47 | You are running $(basename "$0") with root permission, which is not recommended for normal development. 48 | If you need root permission to run docker, please add your account to docker group, reboot, and try again. 49 | EOF 50 | ;; 51 | "$EXIT_MISSING_SUBCOMMAND") 52 | echo "'$2' is not a valid subcommand." >&2 53 | ;; 54 | "$EXIT_FILE_NOT_EXIST") 55 | echo "File '$2' does not exist." >&2 56 | ;; 57 | "$EXIT_AUTHENTICATION_FAILED") 58 | echo "Failed to complete authentication to '$2'." >&2 59 | ;; 60 | "$EXIT_NOT_BLOCK_DEVICE") 61 | echo "'$2' is not a block device." >&2 62 | ;; 63 | "$EXIT_RUNNING_IN_CONTAINER") 64 | echo "'$(basename "$0")' cannot be run in the container. Please try again in a native shell." >&2 65 | ;; 66 | *) 67 | echo "Unknown error code $1." >&2 68 | ;; 69 | esac 70 | 71 | exit "$1" 72 | } 73 | 74 | # Workaround normal sudo can't access nix programs 75 | sudo() { 76 | /usr/bin/env sudo --preserve-env=PATH -s "$@" 77 | } 78 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-chroot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_NAME SCRIPT_DIR 5 | SCRIPT_NAME="$(basename "$0")" 6 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 7 | # shellcheck source=src/lib/rsdk/utils.sh 8 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 9 | 10 | local TEMP 11 | if ! TEMP="$(getopt -o "h" -l "help" -n "$0" -- "$@")"; then 12 | return 13 | fi 14 | eval set -- "$TEMP" 15 | 16 | while true; do 17 | TEMP="$1" 18 | shift 19 | case "$TEMP" in 20 | -h | --help) 21 | rsdk help "${SCRIPT_NAME#rsdk-}" 22 | return 23 | ;; 24 | --) 25 | break 26 | ;; 27 | *) 28 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 29 | ;; 30 | esac 31 | done 32 | 33 | if (($# == 0)); then 34 | "$0" --help 35 | return 36 | fi 37 | 38 | if [[ -f "/.dockerenv" ]]; then 39 | error "$EXIT_RUNNING_IN_CONTAINER" 40 | fi 41 | 42 | if [[ $SCRIPT_NAME == "rsdk-chroot" ]] && (($# < 1)); then 43 | error "$EXIT_TOO_FEW_ARGUMENTS" 44 | elif [[ $SCRIPT_NAME == "rsdk-install" ]] && (($# < 2)); then 45 | error "$EXIT_TOO_FEW_ARGUMENTS" 46 | fi 47 | 48 | disk="$1" 49 | shift 50 | 51 | RSDK_TEMP="$(mktemp -d)" 52 | 53 | if [[ -f $disk ]]; then 54 | disk_file="$disk" 55 | trap 'set +e; sudo -n true && (sudo umount -R "$RSDK_TEMP"; sudo kpartx -d "$disk_file"; sync); rm -rf "$RSDK_TEMP"' SIGINT SIGQUIT SIGTSTP EXIT 56 | sudo kpartx -a "$disk" 57 | echo "Target is a file. Trying to find rootfs partition..." 58 | if ! disk="$(sudo blkid -t LABEL=rootfs -o device | grep /dev/mapper/loop | tail -n 1)" && 59 | ! disk="$(sudo blkid -t PARTLABEL=rootfs -o device | grep /dev/mapper/loop | tail -n 1)" && 60 | ! disk="$(sudo blkid -t LABEL=opi_root -o device | grep /dev/mapper/loop | tail -n 1)"; then 61 | error "$EXIT_BLKDEV_NO_ROOTDEV" "$disk_file" 62 | fi 63 | disk="${disk%p*}p" 64 | fi 65 | 66 | if [[ ! -b $disk ]] && [[ $disk != /dev/mapper/loop* ]]; then 67 | error "$EXIT_NOT_BLOCK_DEVICE" "$disk" 68 | fi 69 | 70 | if [[ -b "$disk"5 ]]; then 71 | # legacy debos-radxa image 72 | sudo mount "$disk"5 "$RSDK_TEMP" 73 | sudo mount "$disk"4 "$RSDK_TEMP/boot" 74 | elif [[ -b "$disk"3 ]]; then 75 | # latest rbuild/rsdk image 76 | sudo mount "$disk"3 "$RSDK_TEMP" 77 | sudo mount "$disk"2 "$RSDK_TEMP/boot/efi" 78 | sudo mount "$disk"1 "$RSDK_TEMP/config" 79 | elif [[ -b "$disk"2 ]]; then 80 | sudo mount "$disk"2 "$RSDK_TEMP" 81 | case "$(sudo blkid "$disk"1 -s LABEL -o value)" in 82 | "armbi_boot" | "opi_boot" | "boot") 83 | # new armbian image / Orange Pi / Rockchip SDK image 84 | sudo mount "$disk"1 "$RSDK_TEMP/boot" 85 | ;; 86 | *) 87 | # old rbuild image 88 | sudo mount "$disk"1 "$RSDK_TEMP/config" 89 | ;; 90 | esac 91 | elif [[ -b "$disk"1 ]]; then 92 | # old armbian image 93 | sudo mount "$disk"1 "$RSDK_TEMP" 94 | else 95 | error "$EXIT_BLKDEV_NO_ROOTDEV" "$disk" 96 | fi 97 | 98 | case "$SCRIPT_NAME" in 99 | rsdk-chroot) 100 | sudo systemd-nspawn -D "$RSDK_TEMP" "$@" 101 | ;; 102 | rsdk-install) 103 | file="${1:-}" 104 | ext="${file##*.}" 105 | case "$ext" in 106 | deb) 107 | sudo cp "$file" "$RSDK_TEMP" 108 | sudo systemd-nspawn -D "$RSDK_TEMP" bash -c \ 109 | "if ! dpkg -i '/$(basename "$file")'; then 110 | apt-get install -y --fix-missing --allow-downgrades || ( 111 | apt-get update; 112 | apt-get install -y --fix-missing --fix-broken --allow-downgrades 113 | ); 114 | fi" 115 | ;; 116 | dtbo) 117 | sudo cp "$file" "$RSDK_TEMP/boot/dtbo" 118 | sudo systemd-nspawn -D "$RSDK_TEMP" u-boot-update 119 | ;; 120 | dtb) 121 | sudo find "$RSDK_TEMP/usr/lib/"linux-image-*/ -name "$(basename "$file")" -exec mv "{}" "{}.bak" \; -exec cp "$file" "{}" \; 122 | ;; 123 | *) 124 | error "$EXIT_UNSUPPORTED_OPTION" "$file" 125 | ;; 126 | esac 127 | ;; 128 | esac 129 | 130 | sudo umount -R "$RSDK_TEMP" 131 | if cut -f 2 -d " " /proc/mounts | grep -q "$RSDK_TEMP"; then 132 | echo "Failed to umount $RSDK_TEMP. Your kernel might report some issues." >&2 133 | exit 1 134 | else 135 | rm -rf "$RSDK_TEMP" 136 | sync 137 | fi 138 | } 139 | 140 | main "$@" 141 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR 5 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 6 | 7 | local TEMP 8 | if ! TEMP="$(getopt -o "hu" -l "help,unset" -n "$0" -- "$@")"; then 9 | return 10 | fi 11 | eval set -- "$TEMP" 12 | 13 | local RSDK_OPTION_UNSET="${RSDK_OPTION_UNSET:-false}" 14 | 15 | while true; do 16 | TEMP="$1" 17 | shift 18 | case "$TEMP" in 19 | -h | --help) 20 | TEMP="$(basename "$0")" 21 | rsdk help "${TEMP#rsdk-}" 22 | return 23 | ;; 24 | -u | --unset) 25 | RSDK_OPTION_UNSET="true" 26 | ;; 27 | --) 28 | break 29 | ;; 30 | *) 31 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 32 | ;; 33 | esac 34 | done 35 | 36 | local FIELD="$1" config_files=( 37 | "$SCRIPT_DIR/../../share/rsdk/configs/rsdk.json" 38 | ) 39 | 40 | if [[ -f .rsdk.json ]]; then 41 | config_files+=(.rsdk.json) 42 | fi 43 | 44 | case $# in 45 | 1) 46 | if [[ $RSDK_OPTION_UNSET == "true" ]]; then 47 | local RSDK_TEMP_JSON 48 | RSDK_TEMP_JSON="$(mktemp)" 49 | jq -er --arg field "$FIELD" 'delpaths([$field / "."])' .rsdk.json >"$RSDK_TEMP_JSON" 50 | mv "$RSDK_TEMP_JSON" .rsdk.json 51 | else 52 | jq -ers --arg field "$FIELD" 'reduce .[] as $i ({}; . * $i) | 53 | if $field == "." then . else getpath($field / ".") end | 54 | if type == "array" then .[] else . end' "${config_files[@]}" 55 | fi 56 | ;; 57 | 2) 58 | local RSDK_TEMP_JSON VALUE="$2" 59 | RSDK_TEMP_JSON="$(mktemp)" 60 | jq -er --arg field "$FIELD" --arg value "$VALUE" 'setpath($field / "."; $value)' .rsdk.json >"$RSDK_TEMP_JSON" 61 | mv "$RSDK_TEMP_JSON" .rsdk.json 62 | ;; 63 | *) 64 | "$0" --help 65 | return 66 | ;; 67 | esac 68 | } 69 | 70 | main "$@" 71 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-devcon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR 5 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 6 | # shellcheck source=src/lib/rsdk/utils.sh 7 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 8 | 9 | if [[ -f /.dockerenv ]]; then 10 | echo "Already inside of container." >&2 11 | exit 1 12 | fi 13 | 14 | local RSDK_ROOT="${DEVENV_ROOT:-$SCRIPT_DIR/../../../}" 15 | 16 | case "${1:-}" in 17 | "build") 18 | devcontainer "${1:-}" --workspace-folder "$RSDK_ROOT" 19 | ;; 20 | "up") 21 | devcontainer "${1:-}" --workspace-folder "$RSDK_ROOT" --remove-existing-container 22 | ;; 23 | "exec" | "") 24 | devcontainer exec --workspace-folder "$RSDK_ROOT" bash 25 | ;; 26 | *) 27 | echo "Unknown command ${1:-}." >&2 28 | exit 1 29 | ;; 30 | esac 31 | } 32 | 33 | main "$@" 34 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rsdk-help-rsdk() { 4 | cat < [suite] [edition] 23 | 24 | ## Options 25 | 26 | --no-cache 27 | Do not use cached build artifacts. This will result in rootfs rebuild. 28 | --no-efi 29 | Do not create EFI partition in the generated image. 30 | -d | --debug 31 | Enable debug output. This will also build rootfs into a folder for easier 32 | examination. 33 | -T | --test-repo 34 | Build using Radxa APT test archives. 35 | -m | --mirror 36 | Specify custom Debian / Ubuntu archive mirror URL. 37 | -M 38 | Specify custom non-Debian non-Ubuntu archive mirror URL. This mirror should 39 | serve both Radxa archives as well as any other 3rd party archives. 40 | 41 | The following archives will use this mirror: 42 | $(find "$SCRIPT_DIR/../../../externals/keyrings/" -maxdepth 1 -mindepth 1 -type d ! -name debian -a ! -name ubuntu -printf " %f\n") 43 | -i | --image-name 44 | Set the system image name. (Default: $("$SCRIPT_DIR/../../bin/rsdk" config build.default_image_name)) 45 | -h | --help 46 | Show this message. 47 | -k | --override-kernel 48 | Override the default kernel profile. Ex: latest, rockchip, rk2312, etc. 49 | -f | --override-firmware 50 | Override the default firmware profile. Ex: latest, rknext, etc. 51 | -p | --override-product 52 | Override the default product profile. Ex: rock-4se, radxa-zero, etc 53 | --no-vendor-packages 54 | Do not install the vendor package specified in product profile. 55 | --debs 56 | Include as the local package archive. 57 | The packages in this archive will be preferred over all other archives. 58 | Packages will be kept even after the build is completed, effectively 59 | disabling any future upgrades on the included packages. 60 | WARNING: the entire content of will be included! 61 | --sdboot 62 | [EXPERIMENTAL] Enable systemd-boot. 63 | This feature is off by default, as U-Boot will try EFI boot first before 64 | Standard boot. 65 | Only supported in some distros. 66 | -s | --sector-size 67 | Override image's sector size. Ex: 512 (default), 4096, etc. 68 | This is used when the local storage has a different sector size compared 69 | to the target storage. 70 | By default, rsdk assumes running on a 512-byte sector storage, building 71 | 512B system image. This option can be used to create 4096B image that is 72 | needed for UFS boot. 73 | Building 512B image on non-512B storage is currently not supported. 74 | EOF 75 | } 76 | 77 | rsdk-help-chroot() { 78 | echo "rsdk-${FUNCNAME[0]##rsdk-help-}" 79 | cat <<'EOF' 80 | ==== 81 | 82 | Enter chroot environment for a given disk or disk image. 83 | 84 | Requires `systemd-nspawn` (provided by `systemd-container` package in Debian). 85 | 86 | ## Command usage 87 | 88 | $ rsdk chroot 89 | 90 | ## Supported target type 91 | 92 | * Raw block devices (i.e. ordinary disks) 93 | * System image file 94 | * Requires `kpartx` (provided by `multipath-tools` package in Debian) 95 | 96 | Following distributions may be used in addition to `rsdk` image: 97 | * `debox-radxa` image 98 | * `rbuild` image 99 | * `rsdk` image 100 | * `Armbian` image 101 | * Orange Pi image 102 | * Rockchip SDK image 103 | EOF 104 | } 105 | 106 | rsdk-help-install() { 107 | echo "rsdk-${FUNCNAME[0]##rsdk-help-}" 108 | cat <<'EOF' 109 | ==== 110 | 111 | Install a build artifacts to a given disk or disk image. 112 | 113 | Requires `systemd-nspawn` (provided by `systemd-container` package in Debian). 114 | 115 | ## Command usage 116 | 117 | $ rsdk install 118 | 119 | ## Supported target type 120 | 121 | * Raw block devices (i.e. ordinary disks) 122 | * System image file 123 | * Requires `kpartx` (provided by `multipath-tools` package in Debian) 124 | 125 | ## Supported artifact type 126 | 127 | * `*.deb`: Debian package 128 | * `*.dtb`: Device tree file 129 | * `*.dtbo`: Device tree overlay file 130 | 131 | Only `rsdk` image supports all artifact types. 132 | Other distributions may have issues on some artifact types. 133 | EOF 134 | } 135 | 136 | main() { 137 | local SCRIPT_DIR 138 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 139 | # shellcheck source=src/lib/rsdk/utils.sh 140 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 141 | 142 | local subcommand="${1:-rsdk}" 143 | shift || true 144 | "rsdk-help-$subcommand" "$@" 145 | } 146 | 147 | main "$@" 148 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR BASE_NAME 5 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 6 | # shellcheck source=src/lib/rsdk/utils.sh 7 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 8 | # shellcheck source=src/lib/rsdk/stdlib.sh 9 | source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh" 10 | BASE_NAME="$(basename "$0")" 11 | 12 | local TEMP 13 | if ! TEMP="$(getopt -o "hptP:s:" -l "help,production,test,prefix:,suffix:" -n "$0" -- "$@")"; then 14 | return 15 | fi 16 | eval set -- "$TEMP" 17 | 18 | export RSDK_WORKFLOW_FILE="${RSDK_WORKFLOW_FILE:-}" 19 | export RSDK_BUILD_ORG="${RSDK_BUILD_ORG:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.organizations.product)}" 20 | export RSDK_APT_REPO_ORG="${RSDK_APT_REPO_ORG:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.organizations.repository)}" 21 | export RSDK_BUILD_TYPE="${RSDK_BUILD_TYPE:-}" 22 | export RSDK_TARGET_PREFIX="${RSDK_TARGET_PREFIX:-}" 23 | export RSDK_TARGET_SUFFIX="${RSDK_TARGET_SUFFIX:-}" 24 | export RSDK_GIT_REPO_TYPE="${RSDK_GIT_REPO_TYPE:-}" 25 | export RSDK_GIT_REPO_ARRAY=("${RSDK_GIT_REPO_ARRAY[@]}") 26 | export RSDK_GIT_REPO_ORG="${RSDK_GIT_REPO_ORG:-}" 27 | 28 | case "$BASE_NAME" in 29 | "rsdk-infra-build") 30 | echo "'$BASE_NAME' cannot be run directly." >&2 31 | echo "Please run one of its symbolic links instead." >&2 32 | return 1 33 | ;; 34 | "rsdk-infra-product-build") 35 | RSDK_GIT_REPO_TYPE="product" 36 | RSDK_GIT_REPO_ORG="${RSDK_GIT_REPO_ORG:-$RSDK_BUILD_ORG}" 37 | mapfile -t RSDK_GIT_REPO_ARRAY < <(jq -er '.[].product' "$SCRIPT_DIR/../../share/rsdk/configs/products.json") && array_remove "RSDK_GIT_REPO_ARRAY" "" 38 | get_workflow() { 39 | case "$RSDK_BUILD_TYPE" in 40 | production) 41 | RSDK_WORKFLOW_FILE="build.yaml" 42 | ;; 43 | test) 44 | RSDK_WORKFLOW_FILE="test.yaml" 45 | ;; 46 | *) 47 | echo "Unknown release variant. Please use -p|--production or -t|--test to specify." >&2 48 | return 1 49 | ;; 50 | esac 51 | } 52 | get_repo_with_modifier() { 53 | echo "$1" 54 | } 55 | ;; 56 | "rsdk-infra-repo-build") 57 | RSDK_GIT_REPO_TYPE="suite" 58 | RSDK_GIT_REPO_ORG="${RSDK_GIT_REPO_ORG:-$RSDK_APT_REPO_ORG}" 59 | mapfile -t RSDK_GIT_REPO_ARRAY < <(jq -er '.[].supported_suites[]' "$SCRIPT_DIR/../../share/rsdk/configs/distributions.json") && array_remove "RSDK_GIT_REPO_ARRAY" "" 60 | get_workflow() { 61 | RSDK_WORKFLOW_FILE="update.yaml" 62 | } 63 | get_repo_with_modifier() { 64 | echo "${RSDK_TARGET_PREFIX}${1}${RSDK_TARGET_SUFFIX}" 65 | } 66 | ;; 67 | *) 68 | echo "Unsupported command '$BASE_NAME'." >&2 69 | return 1 70 | ;; 71 | esac 72 | 73 | while true; do 74 | TEMP="$1" 75 | shift 76 | case "$TEMP" in 77 | -p | --production) 78 | RSDK_BUILD_TYPE="production" 79 | RSDK_TARGET_SUFFIX="" 80 | ;; 81 | -t | --test) 82 | RSDK_BUILD_TYPE="test" 83 | RSDK_TARGET_SUFFIX="-test" 84 | ;; 85 | -P | --prefix) 86 | RSDK_TARGET_PREFIX="$1" 87 | shift 88 | ;; 89 | -s | --suffix) 90 | RSDK_TARGET_SUFFIX="$1" 91 | shift 92 | ;; 93 | -h | --help) 94 | TEMP="$(basename "$0")" 95 | rsdk help "${TEMP#rsdk-}" 96 | return 97 | ;; 98 | --) 99 | break 100 | ;; 101 | *) 102 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 103 | ;; 104 | esac 105 | done 106 | 107 | get_workflow 108 | 109 | if (($# == 0)); then 110 | echo "No $RSDK_GIT_REPO_TYPE supplied." 111 | echo "=============" 112 | echo "Currently, following $RSDK_GIT_REPO_TYPE are supported:" 113 | local i 114 | for i in "${RSDK_GIT_REPO_ARRAY[@]}"; do 115 | get_repo_with_modifier "$i" 116 | done 117 | read -rp "Do you want to build ALL supported ${RSDK_GIT_REPO_TYPE}s? [y/N] " 118 | if [[ ${REPLY/Y/y} != "y" ]]; then 119 | echo "Operation cancelled." 120 | return 1 121 | fi 122 | set -- "${RSDK_GIT_REPO_ARRAY[@]}" 123 | fi 124 | 125 | if ! gh auth status &>/dev/null; then 126 | echo "This operation requires GitHub authentication:" 127 | if ! gh auth login; then 128 | error "$EXIT_AUTHENTICATION_FAILED" "github" 129 | fi 130 | fi 131 | 132 | while (($# != 0)); do 133 | local repo 134 | repo="$(get_repo_with_modifier "$1")" 135 | shift 136 | 137 | gh workflow run ".github/workflows/$RSDK_WORKFLOW_FILE" --repo "$RSDK_GIT_REPO_ORG/$repo" 138 | done 139 | } 140 | 141 | main "$@" 142 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-package-update: -------------------------------------------------------------------------------- 1 | rsdk-infra-update -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-pkg-download: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | find_target_distros() { 4 | local requested=() supported=() deb="$1" pkg_conf="$2" 5 | shift 2 6 | supported=("$@") 7 | 8 | local requested_json i 9 | for i in "$deb" "*"; do 10 | if requested_json="$(jq -er --arg target "$i" 'to_entries[] | select(.key == $target).value.Releases' "$pkg_conf")" && [[ $requested_json != "null" ]]; then 11 | mapfile -t requested < <(jq -er '.[]' <<<"$requested_json") && array_remove "requested" "" 12 | array_intersect "${supported[@]}" -- "${requested[@]}" 13 | return 14 | fi 15 | done 16 | 17 | if [[ $RSDK_OPTION_DEFAULT_DISTRO == "true" ]]; then 18 | echo "${supported[0]}" 19 | fi 20 | } 21 | 22 | download_pkgs() { 23 | local RSDK_TEMP i DISTROS=("$@") OUTPUT="$RSDK_OPTION_DEB_DIR" 24 | RSDK_TEMP="$(mktemp -d)" 25 | for i in "${DISTROS[@]}"; do 26 | mkdir -p "$OUTPUT/$i" 27 | done 28 | 29 | for i in "${!RSDK_PKG_REPO_ARRAY[@]}"; do 30 | request_parallel 31 | ( 32 | org="$RSDK_PACKAGE_ORG" 33 | pkg="${RSDK_PKG_REPO_ARRAY[i]}" 34 | tag="${RSDK_PKG_REPO_TAG_ARRAY[i]}" 35 | 36 | echo "Downloading '$org/$pkg@$tag'..." 37 | mkdir -p "$RSDK_TEMP/$pkg" 38 | 39 | if [[ $RSDK_OPTION_DRY_RUN == "false" ]]; then 40 | gh release download "$tag" --repo "$org/$pkg" --dir "$RSDK_TEMP/$pkg" 41 | if [[ ! -f "$RSDK_TEMP/$pkg/pkg.conf" ]]; then 42 | if [[ $RSDK_OPTION_DEFAULT_DISTRO == "true" ]]; then 43 | cp "$RSDK_TEMP/$pkg"/*.deb "$OUTPUT/${DISTROS[0]}" 44 | else 45 | echo "No pkg.conf found when policy requires explicit distro." 46 | fi 47 | else 48 | for j in "$RSDK_TEMP/$pkg"/*.deb; do 49 | mapfile -t targets < <(find_target_distros "$(basename "$j")" "$RSDK_TEMP/$pkg/pkg.conf" "${DISTROS[@]}") && array_remove "targets" "" 50 | for k in "${targets[@]}"; do 51 | cp "$j" "$OUTPUT/$k" 52 | done 53 | done 54 | fi 55 | fi 56 | ) & 57 | done 58 | wait_parallel 59 | 60 | rm -rf "$RSDK_TEMP" 61 | } 62 | 63 | main() { 64 | local SCRIPT_DIR 65 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 66 | # shellcheck source=src/lib/rsdk/utils.sh 67 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 68 | # shellcheck source=src/lib/rsdk/stdlib.sh 69 | source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh" 70 | 71 | local TEMP 72 | if ! TEMP="$(getopt -o "hd" -l "help,dry-run,deb-dir:,no-default-distro" -n "$0" -- "$@")"; then 73 | return 74 | fi 75 | eval set -- "$TEMP" 76 | 77 | export RSDK_OPTION_DRY_RUN="${RSDK_OPTION_DRY_RUN:-false}" 78 | export RSDK_PACKAGE_ORG="${RSDK_PACKAGE_ORG:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.organizations.package)}" 79 | export RSDK_PKG_REPO_ARRAY=("${RSDK_PKG_REPO_ARRAY[@]}") 80 | export RSDK_PKG_REPO_TAG_ARRAY=("${RSDK_PKG_REPO_TAG_ARRAY[@]}") 81 | export RSDK_OPTION_DEB_DIR="${RSDK_OPTION_DEB_DIR:-${TMPDIR:-/tmp}/rsdk-deb}" 82 | export RSDK_OPTION_DEFAULT_DISTRO="${RSDK_OPTION_DEFAULT_DISTRO:-true}" 83 | 84 | mapfile -t RSDK_PKG_REPO_ARRAY < <(jq -er 'to_entries[].key' pkgs.json) && array_remove "RSDK_PKG_REPO_ARRAY" "" 85 | mapfile -t RSDK_PKG_REPO_TAG_ARRAY < <(jq -er 'to_entries[].value' pkgs.json) && array_remove "RSDK_PKG_REPO_TAG_ARRAY" "" 86 | 87 | while true; do 88 | TEMP="$1" 89 | shift 90 | case "$TEMP" in 91 | -d | --dry-run) 92 | RSDK_OPTION_DRY_RUN="true" 93 | ;; 94 | -h | --help) 95 | TEMP="$(basename "$0")" 96 | rsdk help "${TEMP#rsdk-}" 97 | return 98 | ;; 99 | --deb-dir) 100 | RSDK_OPTION_DEB_DIR="$1" 101 | shift 102 | ;; 103 | --no-default-distro) 104 | RSDK_OPTION_DEFAULT_DISTRO="false" 105 | ;; 106 | --) 107 | break 108 | ;; 109 | *) 110 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 111 | ;; 112 | esac 113 | done 114 | 115 | if (($# == 0)); then 116 | "$0" --help 117 | return 118 | fi 119 | 120 | download_pkgs "$@" 121 | } 122 | 123 | main "$@" 124 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-pkg-snapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR 5 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 6 | # shellcheck source=src/lib/rsdk/utils.sh 7 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 8 | # shellcheck source=src/lib/rsdk/stdlib.sh 9 | source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh" 10 | 11 | local TEMP 12 | if ! TEMP="$(getopt -o "hl:" -l "help,lock-file:" -n "$0" -- "$@")"; then 13 | return 14 | fi 15 | eval set -- "$TEMP" 16 | 17 | export RSDK_PACKAGE_ORG="${RSDK_PACKAGE_ORG:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.organizations.package)}" 18 | export RSDK_PKG_REPO_ARRAY=("${RSDK_PKG_REPO_ARRAY[@]}") 19 | export RSDK_PKG_LOCK_FILE="${RSDK_PKG_LOCK_FILE:-pkgs.lock}" 20 | 21 | while true; do 22 | TEMP="$1" 23 | shift 24 | case "$TEMP" in 25 | -h | --help) 26 | TEMP="$(basename "$0")" 27 | rsdk help "${TEMP#rsdk-}" 28 | return 29 | ;; 30 | -l | --lock-file) 31 | RSDK_PKG_LOCK_FILE="$1" 32 | shift 33 | ;; 34 | --) 35 | break 36 | ;; 37 | *) 38 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 39 | ;; 40 | esac 41 | done 42 | 43 | mapfile -t RSDK_PKG_REPO_ARRAY < <(gh repo list "$RSDK_PACKAGE_ORG" --no-archived --visibility public --limit 65535 --json name --jq '.[].name') && array_remove "RSDK_PKG_REPO_ARRAY" "" 44 | 45 | local RSDK_TEMP p 46 | RSDK_TEMP="$(mktemp -d)" 47 | 48 | for p in "${RSDK_PKG_REPO_ARRAY[@]}"; do 49 | request_parallel 50 | ( 51 | echo "Querying '$RSDK_PACKAGE_ORG/$p'..." 52 | gh release list --exclude-drafts --exclude-pre-releases --json tagName,isLatest --jq ".[] | {\"$p\": select(.isLatest).tagName}" --repo "$RSDK_PACKAGE_ORG/$p" >"$RSDK_TEMP/$p.json" 53 | ) & 54 | done 55 | wait_parallel 56 | 57 | echo "Merging into pkgs.json..." 58 | jq -es 'add' "$RSDK_TEMP"/*.json >pkgs.json 59 | rm -rf "$RSDK_TEMP" 60 | 61 | if [[ -f $RSDK_PKG_LOCK_FILE ]]; then 62 | echo "Applying pkgs.lock..." 63 | local RSDK_TEMP_JSON 64 | RSDK_TEMP_JSON="$(mktemp)" 65 | jq -es 'add | with_entries(select(.value != null))' pkgs.json "$RSDK_PKG_LOCK_FILE" >"$RSDK_TEMP_JSON" 66 | mv "$RSDK_TEMP_JSON" pkgs.json 67 | # Fix file permission for GitHub Pages 68 | # https://github.com/actions/upload-pages-artifact?tab=readme-ov-file#file-permissions 69 | chmod 0644 pkgs.json 70 | fi 71 | } 72 | 73 | main "$@" 74 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-product-build: -------------------------------------------------------------------------------- 1 | rsdk-infra-build -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-product-update: -------------------------------------------------------------------------------- 1 | rsdk-infra-update -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-repo-build: -------------------------------------------------------------------------------- 1 | rsdk-infra-build -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-repo-sync: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | create_archive() { 4 | local i DEB_SOURCE 5 | DEB_SOURCE="$(realpath "$RSDK_OPTION_DEB_DIR")" 6 | 7 | for i in "$@"; do 8 | aptly publish drop -force-drop "$i" "${RSDK_REPO_ORIGIN:-.}" || true 9 | aptly repo drop -force "$i" || true 10 | done 11 | aptly db cleanup 12 | 13 | for i in "$@"; do 14 | aptly repo create -distribution="$i" "$i" 15 | aptly repo add "$i" "$DEB_SOURCE/$i" 16 | local aptly_args=() 17 | if [[ -n $RSDK_REPO_ORIGIN ]]; then 18 | aptly_args+=("-origin=$RSDK_REPO_ORIGIN") 19 | fi 20 | if [[ -n $RSDK_REPO_LABEL ]]; then 21 | aptly_args+=("-label=$RSDK_REPO_LABEL") 22 | fi 23 | aptly publish repo "${aptly_args[@]}" -skip-signing -architectures=all,arm64,armhf,riscv64 "$i" "$RSDK_REPO_ORIGIN" 24 | done 25 | 26 | if [[ $RSDK_OPTION_SKIP_SIGNING == "false" ]]; then 27 | local GPG_PARAMETERS=( 28 | "--yes" 29 | "--armor" 30 | ) 31 | 32 | local keyrings=() key_missing="false" 33 | mapfile -t keyrings < <("$SCRIPT_DIR/../../bin/rsdk" config infra.repository.keyrings) && array_remove "keyrings" "" 34 | for i in "${keyrings[@]}"; do 35 | if ! gpg -K "$i" &>/dev/null; then 36 | echo "Private key for '$i' is not available!" >&2 37 | key_missing="true" 38 | fi 39 | GPG_PARAMETERS+=("-u" "$i") 40 | done 41 | 42 | if [[ $key_missing == "true" ]]; then 43 | echo "Signing failed due to missing private key." >&2 44 | return 1 45 | fi 46 | 47 | for i in "$@"; do 48 | echo "Signing '$i'..." 49 | local DISTRO_PATH="$HOME/.aptly/public/$RSDK_REPO_ORIGIN/dists/$i" 50 | gpg "${GPG_PARAMETERS[@]}" --clear-sign -o "$DISTRO_PATH/InRelease" "$DISTRO_PATH/Release" 51 | gpg "${GPG_PARAMETERS[@]}" --detach-sign -o "$DISTRO_PATH/Release.gpg" "$DISTRO_PATH/Release" 52 | done 53 | fi 54 | } 55 | 56 | main() { 57 | local SCRIPT_DIR 58 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 59 | # shellcheck source=src/lib/rsdk/utils.sh 60 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 61 | # shellcheck source=src/lib/rsdk/stdlib.sh 62 | source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh" 63 | 64 | local TEMP 65 | if ! TEMP="$(getopt -o "hds" -l "help,dry-run,skip-signing,deb-dir:,origin:,label:" -n "$0" -- "$@")"; then 66 | return 67 | fi 68 | eval set -- "$TEMP" 69 | 70 | export RSDK_OPTION_DRY_RUN="${RSDK_OPTION_DRY_RUN:-false}" 71 | export RSDK_OPTION_SKIP_SIGNING="${RSDK_OPTION_SKIP_SIGNING:-false}" 72 | export RSDK_OPTION_DEB_DIR="${RSDK_OPTION_DEB_DIR:-${TMPDIR:-/tmp}/rsdk-deb}" 73 | export RSDK_REPO_ORIGIN="${RSDK_REPO_ORIGIN:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.repository.origin)}" 74 | export RSDK_REPO_LABEL="${RSDK_REPO_LABEL:-$("$SCRIPT_DIR/../../bin/rsdk" config infra.repository.label)}" 75 | 76 | while true; do 77 | TEMP="$1" 78 | shift 79 | case "$TEMP" in 80 | -d | --dry-run) 81 | RSDK_OPTION_DRY_RUN="true" 82 | ;; 83 | -h | --help) 84 | TEMP="$(basename "$0")" 85 | rsdk help "${TEMP#rsdk-}" 86 | return 87 | ;; 88 | -s | --skip-signing) 89 | RSDK_OPTION_SKIP_SIGNING="true" 90 | ;; 91 | --deb-dir) 92 | RSDK_OPTION_DEB_DIR="$1" 93 | shift 94 | ;; 95 | --origin) 96 | RSDK_REPO_ORIGIN="$1" 97 | shift 98 | ;; 99 | --label) 100 | RSDK_REPO_LABEL="$1" 101 | shift 102 | ;; 103 | --) 104 | break 105 | ;; 106 | *) 107 | error "$EXIT_UNKNOWN_OPTION" "$TEMP" 108 | ;; 109 | esac 110 | done 111 | 112 | if (($# == 0)); then 113 | "$0" --help 114 | return 115 | elif [[ ! -e $RSDK_OPTION_DEB_DIR ]]; then 116 | echo "deb-dir is set to '$RSDK_OPTION_DEB_DIR' but it does not exist!" >&2 117 | return 1 118 | fi 119 | 120 | create_archive "$@" 121 | } 122 | 123 | main "$@" 124 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-infra-repo-update: -------------------------------------------------------------------------------- 1 | rsdk-infra-update -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-install: -------------------------------------------------------------------------------- 1 | rsdk-chroot -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-shell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 4 | PROJECT_DIR="$(realpath "$SCRIPT_DIR"/../../../)" 5 | OLD_DIR="$PWD" 6 | 7 | if [[ -n $DEVENV_NIX ]]; then 8 | echo "Already inside of rsdk shell." >&2 9 | exit 1 10 | fi 11 | 12 | pushd "$PROJECT_DIR" || ( 13 | echo "Unable to switch to project folder $PROJECT_DIR." 14 | exit 1 15 | ) 16 | devenv shell -- "$@" 17 | RET="$?" 18 | popd || ( 19 | echo "Unable to return to previous folder $OLD_DIR." 20 | exit 1 21 | ) 22 | 23 | exit "$RET" 24 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-tui: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | __rsdk_build() { 4 | local product 5 | 6 | radiolist_init 7 | local products=() i 8 | mapfile -t products < <(jq -er '.[].product' "$SCRIPT_DIR/../../share/rsdk/configs/products.json") && array_remove "products" "" 9 | for i in "${products[@]}"; do 10 | radiolist_add "$i" "OFF" 11 | done 12 | if ! radiolist_show "Please select a product:" || ((${#RTUI_RADIOLIST_STATE_NEW[@]} == 0)); then 13 | return 14 | fi 15 | product="$(radiolist_getitem "${RTUI_RADIOLIST_STATE_NEW[0]}")" 16 | 17 | if ! yesno "Are you sure to build for '$product'?"; then 18 | return 19 | fi 20 | 21 | rsdk build "$product" 22 | } 23 | 24 | __rsdk_about() { 25 | msgbox "rsdk - RadxaOS Software Development Kit 26 | 27 | Copyright 2024-$(date +%Y) Radxa Computer Co., Ltd" 28 | } 29 | 30 | tui_main() { 31 | menu_init 32 | menu_add __rsdk_build "Build system image" 33 | menu_add_separator 34 | menu_add __rsdk_about "About" 35 | menu_show "Please select a task:" 36 | } 37 | 38 | main() { 39 | local SCRIPT_DIR 40 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 41 | if [[ -f "$SCRIPT_DIR/../../lib/librtui/tui.sh" ]]; then 42 | # shellcheck source=/dev/null 43 | source "$SCRIPT_DIR/../../lib/librtui/tui.sh" 44 | elif [[ -f "$SCRIPT_DIR/../../../externals/librtui/src/lib/librtui/tui.sh" ]]; then 45 | # shellcheck source=externals/librtui/src/lib/librtui/tui.sh 46 | source "$SCRIPT_DIR/../../../externals/librtui/src/lib/librtui/tui.sh" 47 | elif [[ -f "/usr/lib/librtui/tui.sh" ]]; then 48 | # shellcheck source=/dev/null 49 | source "/usr/lib/librtui/tui.sh" 50 | else 51 | echo "Missing librtui. Please make sure you have installed it." >&2 52 | return 1 53 | fi 54 | # shellcheck source=src/lib/rsdk/utils.sh 55 | source "$SCRIPT_DIR/../../lib/rsdk/utils.sh" 56 | # shellcheck source=src/lib/rsdk/stdlib.sh 57 | source "$SCRIPT_DIR/../../lib/rsdk/stdlib.sh" 58 | 59 | local DEBUG="${DEBUG:-false}" 60 | 61 | tui_start tui_main "RSDK" 62 | } 63 | 64 | main "$@" 65 | -------------------------------------------------------------------------------- /src/libexec/rsdk/rsdk-welcome: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | local SCRIPT_DIR 5 | # shellcheck disable=SC2034 6 | SCRIPT_DIR="$(dirname "$(realpath "$0")")" 7 | 8 | cat <&2 48 | xzcat "$IMAGE" 49 | ;; 50 | "gz") 51 | echo "Writing gz image..." >&2 52 | zcat "$IMAGE" 53 | ;; 54 | "zip") 55 | echo "Writing zip image..." >&2 56 | unzip -p "$IMAGE" 57 | ;; 58 | "7z") 59 | echo "Writing 7-zip image..." >&2 60 | 7z e -so "$IMAGE" 61 | ;; 62 | "zstd") 63 | echo "Writing Zstd image..." >&2 64 | zstdcat "$IMAGE" 65 | ;; 66 | "rar") 67 | echo "Writing RAR image..." >&2 68 | 7z e -so "$IMAGE" 69 | ;; 70 | *) 71 | echo "Writing raw image..." >&2 72 | cat "$IMAGE" 73 | ;; 74 | esac 75 | ) | sudo dd "of=$BLOCKDEV" bs=16M status=progress 76 | echo "Syncing block device..." 77 | sudo sync "$BLOCKDEV" 78 | echo "$IMAGE has been written to $BLOCKDEV." 79 | -------------------------------------------------------------------------------- /src/share/man/man8/.gitignore: -------------------------------------------------------------------------------- 1 | /*.8 2 | -------------------------------------------------------------------------------- /src/share/man/man8/rsdk.8.md: -------------------------------------------------------------------------------- 1 | # RSDK(8) 2 | 3 | ## NAME 4 | 5 | rsdk - RadxaOS Software Development Kit 6 | 7 | ## SYNOPSIS 8 | 9 | **rsdk** 10 | 11 | ## DESCRIPTION 12 | 13 | RadxaOS Software Development Kit (rsdk) provides the managed environment to 14 | build system images and essential packages. 15 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/additional_repos.libjsonnet: -------------------------------------------------------------------------------- 1 | local soc_family = import "../../configs/soc_family.libjsonnet"; 2 | local product_soc = import "../../configs/product_soc.libjsonnet"; 3 | local soc_specific_repo = import "../../configs/soc_specific_repo.libjsonnet"; 4 | local product_soc_family(product) = soc_family(product_soc(product)); 5 | local vscodium = import "vscodium.libjsonnet"; 6 | 7 | local radxa_url(radxa_mirror) = ( 8 | if radxa_mirror == "" 9 | then 10 | "https://radxa-repo.github.io/" 11 | else 12 | radxa_mirror 13 | ); 14 | 15 | function(suite, radxa_mirror, radxa_repo_suffix, product, temp_dir, install_vscodium) { 16 | mmdebstrap+: { 17 | packages+: [ 18 | "radxa-archive-keyring", 19 | "local-apt-repository", 20 | ], 21 | "setup-hooks"+: [ 22 | 'mkdir -p "$1/etc/rsdk/"', 23 | ||| 24 | set -e 25 | mkdir -p "$1/srv/" 26 | cp -R "%(temp_dir)s/debs/." "$1/srv/local-apt-repository" 27 | cd "$1/srv/local-apt-repository" 28 | apt-ftparchive packages . > ./Packages 29 | apt-ftparchive -o "APT::FTPArchive::Release::Origin=local-apt-repository" release . > ./Release 30 | cd - 31 | echo "deb [trusted=yes] file://$1/srv/local-apt-repository ./" > "$1/etc/apt/sources.list.d/99-local-apt-repository.list" 32 | cat << EOF > "$1/etc/apt/preferences.d/local-apt-repository" 33 | Package: * 34 | Pin: release o=local-apt-repository 35 | Pin-Priority: 1999 36 | EOF 37 | ||| % { 38 | temp_dir: temp_dir, 39 | }, 40 | ] + (if soc_specific_repo(product_soc(product)) 41 | then 42 | [ 43 | ||| 44 | echo deb %(radxa_url)s%(product_soc)s-%(suite)s %(product_soc)s-%(suite)s main > "$1/etc/apt/sources.list.d/80-radxa-%(product_soc)s.list" 45 | wget -O "$1/etc/rsdk/80-radxa-%(product_soc)s.pkgs.json" %(radxa_url)s%(product_soc)s-%(suite)s/pkgs.json 46 | ||| % { 47 | radxa_url: radxa_url(radxa_mirror), 48 | suite: suite + radxa_repo_suffix, 49 | product_soc: product_soc(product), 50 | } 51 | ] 52 | else 53 | [ 54 | ||| 55 | echo deb %(radxa_url)s%(suite)s %(product_soc_family)s-%(suite)s main > "$1/etc/apt/sources.list.d/80-radxa-%(product_soc_family)s.list" 56 | wget -O "$1/etc/rsdk/80-radxa-%(product_soc_family)s.pkgs.json" %(radxa_url)s%(suite)s/pkgs.json 57 | ||| % { 58 | radxa_url: radxa_url(radxa_mirror), 59 | suite: suite + radxa_repo_suffix, 60 | product_soc_family: product_soc_family(product), 61 | } 62 | ] 63 | ) + [ 64 | ||| 65 | echo deb %(radxa_url)s%(suite)s %(suite)s main > "$1/etc/apt/sources.list.d/70-radxa.list" 66 | wget -O "$1/etc/rsdk/70-radxa.pkgs.json" %(radxa_url)s%(suite)s/pkgs.json 67 | ||| % { 68 | radxa_url: radxa_url(radxa_mirror), 69 | suite: suite + radxa_repo_suffix, 70 | }, 71 | 'curl -L -o "$1/etc/radxa_apt_snapshot" %(radxa_url)s%(suite)s/pkgs.json' 72 | % { 73 | radxa_url: radxa_url(radxa_mirror), 74 | suite: suite + radxa_repo_suffix, 75 | }, 76 | ], 77 | "customize-hooks"+: [ 78 | ||| 79 | set -e 80 | export SYSTEMD_RELAX_ESP_CHECKS=1 81 | 82 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get update -oDPkg::Chroot-Directory="$1" 83 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 apt-get full-upgrade -oDPkg::Chroot-Directory="$1" -y --allow-downgrades 84 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 apt-get autoremove -oDPkg::Chroot-Directory="$1" -y --purge 85 | sed -i "s|^deb|deb [signed-by=\"/usr/share/keyrings/radxa-archive-keyring.gpg\"]|g" "$1"/etc/apt/sources.list.d/*-radxa*.list 86 | rm "$1/etc/apt/sources.list.d/99-local-apt-repository.list" 87 | rm "$1/srv/local-apt-repository/Packages" 88 | rm "$1/srv/local-apt-repository/Release" 89 | |||, 90 | ], 91 | } 92 | } + (if install_vscodium 93 | then 94 | vscodium(suite, radxa_mirror) 95 | else 96 | {} 97 | ) 98 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/cleanup.libjsonnet: -------------------------------------------------------------------------------- 1 | function() { 2 | mmdebstrap+: { 3 | "cleanup-hooks"+: [ 4 | // delete DNS conf which is specific to the build environment 5 | 'rm -rf "$1/etc/resolv.conf"', 6 | 'rm -rf "$1/var/lib/apt/lists"/*', 7 | 'rm -rf "$1/etc/machine-id" "$1/var/lib/dbus/machine-id"', 8 | 'rm -rf "$1/var/log/journal"/*', 9 | ], 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/distro.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_check = import "../../configs/distro_check.libjsonnet"; 2 | 3 | local distro_base(suite, distro_mirror, distro, architecture, distro_mirror_default) = { 4 | mmdebstrap+: { 5 | components+: [ 6 | "main", 7 | ], 8 | mirrors+: [ 9 | // Primary archive 10 | (if distro_mirror == "" 11 | then 12 | distro_mirror_default 13 | else 14 | distro_mirror) 15 | + "/" + 16 | (if distro == "ubuntu" && architecture != "amd64" 17 | then 18 | distro + "-ports" 19 | else 20 | distro), 21 | ], 22 | "setup-hooks"+: [ 23 | ||| 24 | # updates archive 25 | head -n 1 "$1/etc/apt/sources.list" | sed -E -e "s/(%(suite)s)/\\1-updates/" > "$1/etc/apt/sources.list.d/50-%(suite)s-updates.list" 26 | # backports archive 27 | head -n 1 "$1/etc/apt/sources.list" | sed -E -e "s/(%(suite)s)/\\1-backports/" > "$1/etc/apt/sources.list.d/50-%(suite)s-backports.list" 28 | # security archive 29 | head -n 1 "$1/etc/apt/sources.list" | sed -E -e "s/(%(suite)s)/\\1-security/" -e "s|/debian |/debian-security |" > "$1/etc/apt/sources.list.d/50-%(suite)s-security.list" 30 | # main archive 31 | mv "$1/etc/apt/sources.list" "$1/etc/apt/sources.list.d/50-%(suite)s.list" 32 | ||| % { 33 | suite: suite 34 | }, 35 | ], 36 | suite+: suite, 37 | } 38 | }; 39 | 40 | local distro_debian( 41 | suite, 42 | distro_mirror, 43 | architecture, 44 | distro = "debian", 45 | ) = distro_base(suite, distro_mirror, distro, architecture, "https://deb.debian.org") + { 46 | mmdebstrap+: { 47 | components+: std.prune([ 48 | "contrib", 49 | "non-free", 50 | if suite == "bookworm" || suite == "trixie" then "non-free-firmware", 51 | ]) 52 | } 53 | }; 54 | 55 | local distro_ubuntu( 56 | suite, 57 | distro_mirror, 58 | architecture, 59 | distro = "ubuntu", 60 | ) = distro_base(suite, distro_mirror, distro, architecture, "http://ports.ubuntu.com") + { 61 | mmdebstrap+: { 62 | components+: [ 63 | "restricted", 64 | "universe", 65 | "multiverse", 66 | ] 67 | } 68 | }; 69 | 70 | function(suite, distro_mirror, architecture) 71 | if distro_check(suite) == "debian" 72 | then 73 | distro_debian(suite, distro_mirror, architecture) 74 | else if distro_check(suite) == "ubuntu" 75 | then 76 | distro_ubuntu(suite, distro_mirror, architecture) 77 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages.libjsonnet: -------------------------------------------------------------------------------- 1 | local cli_packages = import "packages/cli.libjsonnet"; 2 | local sway_packages = import "packages/sway.libjsonnet"; 3 | local kde_packages = import "packages/kde.libjsonnet"; 4 | local xfce_packages = import "packages/xfce.libjsonnet"; 5 | local core_packages = import "packages/core.libjsonnet"; 6 | local i3_packages = import "packages/i3.libjsonnet"; 7 | local gnome_packages = import "packages/gnome.libjsonnet"; 8 | 9 | function(suite, edition, product, temp_dir, vendor_packages, linux_override, firmware_override,) ( 10 | if edition == "cli" 11 | then 12 | cli_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 13 | else if edition == "kde" 14 | then 15 | kde_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 16 | else if edition == "xfce" 17 | then 18 | xfce_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 19 | else if edition == "sway" 20 | then 21 | sway_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 22 | else if edition == "i3" 23 | then 24 | i3_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 25 | else if edition == "core" 26 | then 27 | core_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 28 | else if edition == "gnome" 29 | then 30 | gnome_packages(suite, product, temp_dir, vendor_packages, linux_override, firmware_override,) 31 | ) 32 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/categories/base.libjsonnet: -------------------------------------------------------------------------------- 1 | local core_packages = import "core.libjsonnet"; 2 | local distro_check = import "../../../../configs/distro_check.libjsonnet"; 3 | 4 | function(suite, 5 | product, 6 | temp_dir, 7 | vendor_packages, 8 | linux_override, 9 | firmware_override, 10 | ) core_packages(suite, 11 | product, 12 | temp_dir, 13 | vendor_packages, 14 | linux_override, 15 | firmware_override, 16 | ) + { 17 | mmdebstrap+: { 18 | packages+: 19 | // Firmware 20 | (if distro_check(suite) == "debian" 21 | then 22 | [ 23 | "firmware-iwlwifi", 24 | "firmware-linux", 25 | ] 26 | else 27 | [] 28 | ) + 29 | [ 30 | // System utils 31 | "apt-listchanges", 32 | "apt-transport-https", 33 | "apt-utils", 34 | "bash-completion", 35 | "bc", 36 | "binutils", 37 | "curl", 38 | "dmidecode", 39 | "eject", 40 | "exfat-fuse", 41 | "file", 42 | "gpg", 43 | "haveged", 44 | "htop", 45 | "lbzip2", 46 | "less", 47 | "locales", 48 | "lm-sensors", 49 | "man-db", 50 | "nano", 51 | "needrestart", 52 | "ntfs-3g", 53 | "python3-pip", 54 | "software-properties-common", 55 | "tmux", 56 | "vim", 57 | "wget", 58 | "xz-utils", 59 | ] + 60 | 61 | [ 62 | // Network 63 | "avahi-daemon", 64 | "ca-certificates", 65 | "dnsmasq", 66 | "ldnsutils", 67 | "iproute2", 68 | "iptables", 69 | "iputils-ping", 70 | "samba", 71 | "wireless-regdb", 72 | ] + 73 | 74 | [ 75 | // Audio 76 | "alsa-ucm-conf", 77 | "alsa-utils", 78 | ] + 79 | 80 | (if suite == "bookworm" 81 | then 82 | [ 83 | "pipewire-audio", 84 | ] 85 | else 86 | [ 87 | "pulseaudio", 88 | "pulseaudio-module-bluetooth", 89 | ] 90 | ) + 91 | 92 | [ 93 | // Hardware 94 | "gpiod", 95 | "hdparm", 96 | "i2c-tools", 97 | "mtd-utils", 98 | "pciutils", 99 | "rfkill", 100 | "spi-tools", 101 | "usbutils", 102 | ] + 103 | 104 | [ 105 | // Radxa 106 | "android-tools-adbd", 107 | "libreelec-alsa-utils", 108 | "radxa-otgutils", 109 | ] + 110 | 111 | [ 112 | // Misc 113 | "libmraa2", 114 | "libmraa-dev", 115 | "libopencv-dev", 116 | ], 117 | 118 | "customize-hooks"+: 119 | (if distro_check(suite) == "debian" 120 | then 121 | [ 122 | 'chroot "$1" update-alternatives --set regulatory.db /lib/firmware/regulatory.db-upstream', 123 | ] 124 | else 125 | [] 126 | ), 127 | }, 128 | } 129 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/categories/core.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_check = import "../../../../configs/distro_check.libjsonnet"; 2 | local product_firmware_type = import "../../../../configs/product_firmware_type.libjsonnet"; 3 | 4 | function(suite, 5 | product, 6 | temp_dir, 7 | vendor_packages, 8 | linux_override, 9 | firmware_override, 10 | ) { 11 | mmdebstrap+: { 12 | packages+: 13 | [ 14 | // Core system package 15 | "init", 16 | "sudo", 17 | ] + 18 | 19 | // Firmware 20 | (if distro_check(suite) == "debian" 21 | then 22 | [ 23 | "firmware-brcm80211", 24 | "firmware-realtek", 25 | ] 26 | else if distro_check(suite) == "ubuntu" 27 | then 28 | [ 29 | "linux-firmware", 30 | ] 31 | else 32 | [] 33 | ) + 34 | 35 | [ 36 | // System utils 37 | "cloud-initramfs-growroot", 38 | "ssh", 39 | "systemd-timesyncd", 40 | ] + 41 | 42 | [ 43 | // Network 44 | "bluetooth", 45 | "iw", 46 | ] + 47 | 48 | (if suite == "bullseye" 49 | then 50 | [ 51 | "libnm0/bullseye-backports", 52 | "network-manager/bullseye-backports", 53 | "wpasupplicant/bullseye-backports", 54 | 55 | ] 56 | else 57 | [ 58 | "network-manager", 59 | "wpasupplicant", 60 | ] 61 | ) + 62 | 63 | (if suite == "bookworm" 64 | then 65 | [ 66 | "efibootmgr", 67 | "systemd-boot", 68 | ] 69 | else 70 | [] 71 | ) + 72 | 73 | [ 74 | // Radxa 75 | "radxa-firmware", 76 | "radxa-udev", 77 | "rsetup-config-first-boot", 78 | ], 79 | 80 | "essential-hooks"+: 81 | [ 82 | ||| 83 | set -e 84 | 85 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 86 | apt-get install -oDPkg::Chroot-Directory="$1" -y \ 87 | rsetup radxa-bootutils python-is-python3 initramfs-tools 88 | 89 | mkdir -p "$1/boot/efi" 90 | mount -t tmpfs rsdk "$1/boot/efi" 91 | |||, 92 | (if suite == "bookworm" && (std.extVar("sdboot") || product_firmware_type(product) == "edk2") 93 | then 94 | ||| 95 | set -e 96 | 97 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 98 | apt-get install -oDPkg::Chroot-Directory="$1" -y \ 99 | systemd-boot 100 | chroot "$1" sh -c "SYSTEMD_RELAX_ESP_CHECKS=1 bootctl install --esp-path=/boot/efi/ --no-variables --entry-token=literal:RadxaOS" 101 | sed -i "s/#timeout/timeout/" "$1/boot/efi/loader/loader.conf" 102 | ||| 103 | else 104 | "echo 'Skip systemd-boot installation.'" 105 | ), 106 | ||| 107 | set -e 108 | export SYSTEMD_RELAX_ESP_CHECKS=1 109 | 110 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 111 | apt-get install -oDPkg::Chroot-Directory="$1" -y \ 112 | %(firmware)s-%(firmware_override)s linux-headers-%(linux_override)s 113 | 114 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 115 | apt-get install -oDPkg::Chroot-Directory="$1" -y \ 116 | linux-image-%(linux_override)s 117 | 118 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 119 | apt-get install -oDPkg::Chroot-Directory="$1" -y \ 120 | -oDpkg::Options::=--force-confnew %(recommends)s \ 121 | task-%(product)s 122 | 123 | APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" \ 124 | apt-get full-upgrade -oDPkg::Chroot-Directory="$1" -y \ 125 | -oDpkg::Options::=--force-confnew --allow-downgrades 126 | ||| % { 127 | recommends: (if distro_check(suite) == "debian" && vendor_packages 128 | then 129 | "--install-recommends" 130 | else 131 | "--no-install-recommends" 132 | ), 133 | product: product, 134 | firmware: product_firmware_type(product), 135 | firmware_override: (if std.length(firmware_override) == 0 136 | then 137 | product 138 | else 139 | firmware_override 140 | ), 141 | linux_override: (if std.length(linux_override) == 0 142 | then 143 | product 144 | else 145 | linux_override 146 | ), 147 | }, 148 | ], 149 | }, 150 | } 151 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/categories/desktop.libjsonnet: -------------------------------------------------------------------------------- 1 | local base_packages = import "base.libjsonnet"; 2 | local distro_check = import "../../../../configs/distro_check.libjsonnet"; 3 | 4 | function(suite, 5 | product, 6 | temp_dir, 7 | vendor_packages, 8 | linux_override, 9 | firmware_override, 10 | ) base_packages(suite, 11 | product, 12 | temp_dir, 13 | vendor_packages, 14 | linux_override, 15 | firmware_override, 16 | ) + { 17 | mmdebstrap+: { 18 | packages+: 19 | [ 20 | "accountsservice", 21 | "aha", 22 | "breeze-cursor-theme", 23 | "clinfo", 24 | "cups", 25 | "desktop-base", 26 | "fonts-noto-cjk", 27 | "fprintd", 28 | "fwupd", 29 | "gstreamer1.0-gtk3", 30 | "gstreamer1.0-libav", 31 | "gstreamer1.0-plugins-bad", 32 | "gstreamer1.0-plugins-base", 33 | "gstreamer1.0-plugins-good", 34 | "gstreamer1.0-plugins-rtp", 35 | "gstreamer1.0-plugins-ugly", 36 | "gstreamer1.0-qt5", 37 | "gstreamer1.0-vaapi", 38 | "gvfs", 39 | "gvfs-backends", 40 | "gvfs-fuse", 41 | "mesa-utils", 42 | "mesa-va-drivers", 43 | "plymouth", 44 | "plymouth-theme-breeze", 45 | "plymouth-themes", 46 | "rtkit", 47 | "vdpau-driver-all", 48 | "vulkan-tools", 49 | "xdg-desktop-portal", 50 | "xdg-desktop-portal-gtk", 51 | "xdg-user-dirs", 52 | "xdg-user-dirs-gtk", 53 | "xdg-utils", 54 | ] + 55 | 56 | (if distro_check(suite) == "debian" 57 | then 58 | [ 59 | "firefox-esr", 60 | "maliit-keyboard", 61 | ] 62 | else if distro_check(suite) == "ubuntu" 63 | then 64 | [ 65 | "firefox", 66 | ] 67 | else 68 | [] 69 | ) + 70 | 71 | (if suite != "focal" 72 | then 73 | [ 74 | "bup", 75 | ] 76 | else 77 | [] 78 | ) + 79 | 80 | (if suite == "bookworm" 81 | then 82 | // Install Debian 12 packages 83 | [ 84 | "wayland-utils", 85 | "gstreamer1.0-pipewire", 86 | ] 87 | else 88 | // Install common X.Org packages 89 | [ 90 | "xiccd", 91 | ] 92 | ), 93 | }, 94 | } 95 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/cli.libjsonnet: -------------------------------------------------------------------------------- 1 | local base_packages = import "categories/base.libjsonnet"; 2 | 3 | function(suite, 4 | product, 5 | temp_dir, 6 | vendor_packages, 7 | linux_override, 8 | firmware_override, 9 | ) base_packages(suite, 10 | product, 11 | temp_dir, 12 | vendor_packages, 13 | linux_override, 14 | firmware_override, 15 | ) 16 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/core.libjsonnet: -------------------------------------------------------------------------------- 1 | local core_packages = import "categories/core.libjsonnet"; 2 | 3 | function(suite, 4 | product, 5 | temp_dir, 6 | vendor_packages, 7 | linux_override, 8 | firmware_override, 9 | ) core_packages(suite, 10 | product, 11 | temp_dir, 12 | vendor_packages, 13 | linux_override, 14 | firmware_override, 15 | ) 16 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/gdm.libjsonnet: -------------------------------------------------------------------------------- 1 | function() { 2 | mmdebstrap+: { 3 | packages+: [ "gdm3" ], 4 | "customize-hooks"+: 5 | [ 6 | // Manually set gdm3 as the default display manager, as dpkg-reconfigure does not work under chroot 7 | ||| 8 | echo "gdm3 shared/default-x-display-manager select gdm3" | chroot "$1" debconf-set-selections 9 | echo "/usr/sbin/gdm3" > "$1/etc/X11/default-display-manager" 10 | ln -sf "/lib/systemd/system/gdm3.service" "$1/etc/systemd/system/display-manager.service" 11 | ||| 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/gnome.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_check = import "../../../configs/distro_check.libjsonnet"; 2 | local desktop_packages = import "categories/desktop.libjsonnet"; 3 | 4 | function(suite, 5 | product, 6 | temp_dir, 7 | vendor_packages, 8 | linux_override, 9 | firmware_override, 10 | ) desktop_packages(suite, 11 | product, 12 | temp_dir, 13 | vendor_packages, 14 | linux_override, 15 | firmware_override, 16 | ) + { 17 | mmdebstrap+: { 18 | packages+: 19 | [ 20 | "task-gnome-desktop", 21 | ], 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/i3.libjsonnet: -------------------------------------------------------------------------------- 1 | local desktop_packages = import "categories/desktop.libjsonnet"; 2 | 3 | function(suite, 4 | product, 5 | temp_dir, 6 | vendor_packages, 7 | linux_override, 8 | firmware_override, 9 | ) desktop_packages(suite, 10 | product, 11 | temp_dir, 12 | vendor_packages, 13 | linux_override, 14 | firmware_override, 15 | ) + { 16 | mmdebstrap+: { 17 | packages+: 18 | [ 19 | "i3", 20 | "i3status", 21 | "suckless-tools", 22 | "stterm", 23 | "xinit", 24 | "xserver-xorg-input-libinput", 25 | ] + 26 | 27 | (if suite == "bookworm" 28 | then 29 | // Install Debian 12 packages 30 | [ 31 | "greetd", 32 | ] 33 | else 34 | [] 35 | ), 36 | "customize-hooks"+: 37 | [ 38 | 'mkdir -p "$1/etc/skel/.config/i3"', 39 | 'cp "$1/etc/i3/config" "$1/etc/skel/.config/i3/config"', 40 | 'chroot "$1" update-alternatives --set x-terminal-emulator /usr/bin/st', 41 | ] 42 | }, 43 | } 44 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/kde.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_check = import "../../../configs/distro_check.libjsonnet"; 2 | local desktop_packages = import "categories/desktop.libjsonnet"; 3 | local product_soc = import "../../../configs/product_soc.libjsonnet"; 4 | local soc_family = import "../../../configs/soc_family.libjsonnet"; 5 | local gdm = import "gdm.libjsonnet"; 6 | 7 | function(suite, 8 | product, 9 | temp_dir, 10 | vendor_packages, 11 | linux_override, 12 | firmware_override, 13 | ) desktop_packages(suite, 14 | product, 15 | temp_dir, 16 | vendor_packages, 17 | linux_override, 18 | firmware_override, 19 | ) + { 20 | mmdebstrap+: { 21 | packages+: 22 | [ 23 | "accountwizard", 24 | "bluedevil", 25 | "dragonplayer", 26 | "kamera", 27 | "kde-config-plymouth", 28 | "kde-config-screenlocker", 29 | "kde-config-sddm", 30 | "kdeconnect", 31 | "khotkeys", 32 | "kinfocenter", 33 | "kio-extras", 34 | "konqueror", 35 | "kscreen", 36 | "kup-backup", 37 | "kwin-x11", 38 | "libkf5kdelibs4support5", 39 | "libkf5kdelibs4support5-bin", 40 | "phonon4qt5-backend-gstreamer", 41 | "phonon4qt5settings", 42 | "plasma-discover", 43 | "plasma-nm", 44 | "powerdevil", 45 | "print-manager", 46 | "qtvirtualkeyboard-plugin", 47 | "qml-module-org-kde-newstuff", 48 | "qml-module-qt-labs-platform", 49 | "sddm-theme-breeze", 50 | "sonnet-plugins", 51 | "systemsettings", 52 | "yakuake", 53 | "xdg-desktop-portal-kde", 54 | ] + 55 | 56 | (if distro_check(suite) == "debian" 57 | then 58 | [ 59 | "task-kde-desktop", 60 | ] 61 | else if distro_check(suite) == "ubuntu" 62 | then 63 | [ 64 | "kubuntu-desktop", 65 | ] 66 | else 67 | [] 68 | ) + 69 | 70 | (if suite != "focal" 71 | then 72 | [ 73 | "kde-config-systemd", 74 | ] 75 | else 76 | [] 77 | ) + 78 | 79 | (if suite == "bookworm" 80 | then 81 | // Install Debian 12 packages 82 | [ 83 | "plasma-workspace-wayland", 84 | "qml-module-org-kde-pipewire", 85 | ] 86 | else 87 | [] 88 | ), 89 | }, 90 | } + (if suite == "bookworm" 91 | then 92 | // Debian 12's sddm has issue handling screen hotplug, as well as screen wake up 93 | // https://applink.feishu.cn/client/message/link/open?token=AmY%2FRdMxxQABZoS475OOwAQ%3D 94 | // https://vamrs.feishu.cn/sheets/IFXSs271ThaBVytTCVbcMcxsnpc?sheet=0KtklS&rangeId=0KtklS_iOZ0zYhC18&rangeVer=1 95 | gdm() 96 | else 97 | {} 98 | ) 99 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/sway.libjsonnet: -------------------------------------------------------------------------------- 1 | local desktop_packages = import "categories/desktop.libjsonnet"; 2 | 3 | function(suite, 4 | product, 5 | temp_dir, 6 | vendor_packages, 7 | linux_override, 8 | firmware_override, 9 | ) desktop_packages(suite, 10 | product, 11 | temp_dir, 12 | vendor_packages, 13 | linux_override, 14 | firmware_override, 15 | ) + { 16 | mmdebstrap+: { 17 | packages+: 18 | [ 19 | "foot", 20 | "suckless-tools", 21 | "sway", 22 | "sway-backgrounds", 23 | "swaybg", 24 | "swayidle", 25 | "xdg-desktop-portal-wlr", 26 | "xwayland", 27 | ] + 28 | 29 | (if suite == "bookworm" 30 | then 31 | // Install Debian 12 packages 32 | [ 33 | "greetd", 34 | "swaylock", 35 | ] 36 | else 37 | [] 38 | ), 39 | "customize-hooks"+: 40 | [ 41 | 'mkdir -p "$1/etc/skel/.config/foot"', 42 | '[ -f "$1/etc/xdg/foot/foot.ini" ] && cp "$1/etc/xdg/foot/foot.ini" "$1/etc/skel/.config/foot/foot.ini" || true', 43 | 'mkdir -p "$1/etc/skel/.config/sway"', 44 | 'cp "$1/etc/sway/config" "$1/etc/skel/.config/sway/config"', 45 | ] 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/packages/xfce.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_check = import "../../../configs/distro_check.libjsonnet"; 2 | local desktop_packages = import "categories/desktop.libjsonnet"; 3 | 4 | function(suite, 5 | product, 6 | temp_dir, 7 | vendor_packages, 8 | linux_override, 9 | firmware_override, 10 | ) desktop_packages(suite, 11 | product, 12 | temp_dir, 13 | vendor_packages, 14 | linux_override, 15 | firmware_override, 16 | ) + { 17 | mmdebstrap+: { 18 | packages+: 19 | [ 20 | "blueman", 21 | "light-locker", 22 | "network-manager-gnome", 23 | "parole", 24 | "pavucontrol", 25 | "thunar-volman", 26 | "xfce4-clipman", 27 | "xfce4-notifyd", 28 | "xfce4-power-manager", 29 | "xfce4-screenshooter", 30 | "xfce4-terminal", 31 | 'xfce4-screensaver', 32 | ] + 33 | 34 | (if distro_check(suite) == "debian" 35 | then 36 | [ 37 | "task-xfce-desktop", 38 | ] 39 | else if distro_check(suite) == "ubuntu" 40 | then 41 | [ 42 | "xfce4", 43 | ] 44 | else 45 | [] 46 | ), 47 | "customize-hooks"+: [ 48 | // Remove light-locker in favor of xfce4-screensaver 49 | 'APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 apt-get remove -oDPkg::Chroot-Directory="$1" -y light-locker', 50 | ] 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /src/share/rsdk/build/mod/vscodium.libjsonnet: -------------------------------------------------------------------------------- 1 | local vscodium_url(radxa_mirror) = ( 2 | if radxa_mirror == "" 3 | then 4 | "https://download.vscodium.com/" 5 | else 6 | radxa_mirror 7 | ) + "debs"; 8 | 9 | function(suite, radxa_mirror) { 10 | mmdebstrap+: { 11 | packages+: [ 12 | "vscodium-archive-keyring", 13 | ] + (if suite != "core" && suite != "cli" 14 | then 15 | [ "codium" ] 16 | else 17 | [] 18 | ), 19 | "setup-hooks"+: [ 20 | 'echo deb %(vscodium_url)s vscodium main > "$1/etc/apt/sources.list.d/90-vscodium.list"' 21 | % { 22 | vscodium_url: vscodium_url(radxa_mirror) 23 | }, 24 | ], 25 | "customize-hooks"+: [ 26 | ||| 27 | sed -i "s|^deb|deb [signed-by=\"/usr/share/keyrings/vscodium-archive-keyring.gpg\"]|g" "$1"/etc/apt/sources.list.d/90-vscodium.list 28 | |||, 29 | ], 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/share/rsdk/build/rootfs.jsonnet: -------------------------------------------------------------------------------- 1 | local distro = import "mod/distro.libjsonnet"; 2 | local additional_repos = import "mod/additional_repos.libjsonnet"; 3 | local packages = import "mod/packages.libjsonnet"; 4 | local cleanup = import "mod/cleanup.libjsonnet"; 5 | 6 | function( 7 | architecture = "arm64", 8 | mode = "root", 9 | rootfs = "rootfs.tar", 10 | variant = "apt", 11 | 12 | temp_dir, 13 | output_dir, 14 | rsdk_rev = "", 15 | 16 | distro_mirror = "", 17 | 18 | radxa_mirror = "", 19 | radxa_repo_suffix = "", 20 | 21 | product, 22 | suite, 23 | edition, 24 | build_date, 25 | 26 | vendor_packages = true, 27 | linux_override = "", 28 | firmware_override = "", 29 | install_vscodium = false, 30 | ) distro(suite, distro_mirror, architecture) 31 | + additional_repos(suite, radxa_mirror, radxa_repo_suffix, product, temp_dir, install_vscodium) 32 | + packages(suite, edition, product, temp_dir, vendor_packages, linux_override, firmware_override) 33 | + cleanup() 34 | + { 35 | mmdebstrap+: { 36 | architectures: [ 37 | architecture 38 | ], 39 | keyrings: [ 40 | "%(temp_dir)s/keyrings/" % { temp_dir: temp_dir }, 41 | ], 42 | mode: mode, 43 | target: rootfs, 44 | variant: variant, 45 | hostname: product, 46 | packages+: 47 | [ 48 | // Adding additional packages to the system 49 | // For example: 50 | // "nano", 51 | ], 52 | "customize-hooks"+: 53 | [ 54 | 'echo "127.0.1.1 %(product)s" >> "$1/etc/hosts"' % { product: product }, 55 | 'cp "%(output_dir)s/config.yaml" "$1/etc/rsdk/"' % { output_dir: output_dir }, 56 | 'echo "FINGERPRINT_VERSION=\'2\'" > "$1/etc/radxa_image_fingerprint"', 57 | 'echo "RSDK_BUILD_DATE=\'$(date -R)\'" >> "$1/etc/radxa_image_fingerprint"', 58 | 'echo "RSDK_REVISION=\'%(rsdk_rev)s\'" >> "$1/etc/radxa_image_fingerprint"' % { rsdk_rev: rsdk_rev }, 59 | 'echo "RSDK_CONFIG=\'/etc/rsdk/config.yaml\'" >> "$1/etc/radxa_image_fingerprint"', 60 | 'chroot "$1" sh -c "SYSTEMD_RELAX_ESP_CHECKS=1 update-initramfs -c -k all"', 61 | 'chroot "$1" sh -c "u-boot-update"', 62 | ||| 63 | cp -aR "$1/boot/efi" "$1/boot/efi2" 64 | chmod 0755 "$1/boot/efi2" 65 | umount "$1/boot/efi" 66 | rmdir "$1/boot/efi" 67 | mv "$1/boot/efi2" "$1/boot/efi" 68 | |||, 69 | ||| 70 | mkdir -p "%(output_dir)s/seed" 71 | cp "$1/etc/radxa_image_fingerprint" "%(output_dir)s/seed" 72 | cp "$1/etc/rsdk/"* "%(output_dir)s/seed" 73 | tar Jvcf "%(output_dir)s/seed.tar.xz" -C "%(output_dir)s/seed" . 74 | rm -rf "%(output_dir)s/seed" 75 | ||| % { output_dir: output_dir }, 76 | // Adding additional customization commands 77 | // $1 is the mounted rootfs than you can chroot into 78 | // For example: 79 | // ||| 80 | // set -e 81 | // wget -O $1/tmp/your.deb https://example.com/your.deb 82 | // chroot "$1" dpkg -i /tmp/your.deb 83 | // rm $1/tmp/your.deb 84 | // |||, 85 | ] 86 | }, 87 | metadata: { 88 | architecture: architecture, 89 | mode: mode, 90 | rootfs: rootfs, 91 | variant: variant, 92 | 93 | temp_dir: temp_dir, 94 | output_dir: output_dir, 95 | rsdk_rev: rsdk_rev, 96 | 97 | distro_mirror: distro_mirror, 98 | 99 | radxa_mirror: radxa_mirror, 100 | radxa_repo_suffix: radxa_repo_suffix, 101 | 102 | product: product, 103 | suite: suite, 104 | edition: edition, 105 | build_date: build_date, 106 | 107 | vendor_packages: vendor_packages, 108 | linux_override: linux_override, 109 | firmware_override: firmware_override, 110 | install_vscodium: install_vscodium, 111 | sdboot: std.extVar("sdboot"), 112 | }, 113 | } -------------------------------------------------------------------------------- /src/share/rsdk/common/check_linked_issue/check_linked_issue.yaml.jsonnet: -------------------------------------------------------------------------------- 1 | function() std.manifestYamlDoc( 2 | { 3 | name: "Check linked issues", 4 | on: { 5 | pull_request_target: { 6 | types: [ 7 | "opened", 8 | "reopened", 9 | ], 10 | }, 11 | }, 12 | permissions: {}, 13 | jobs: { 14 | check_pull_requests: { 15 | "runs-on": "ubuntu-latest", 16 | name: "Check linked issues", 17 | permissions: { 18 | issues: "write", 19 | "pull-requests": "write", 20 | }, 21 | steps: [ 22 | { 23 | name: "Check linked issues", 24 | uses: "nearform-actions/github-action-check-linked-issues@v1", 25 | }, 26 | ], 27 | }, 28 | } 29 | }, 30 | quote_keys=false, 31 | ) 32 | -------------------------------------------------------------------------------- /src/share/rsdk/common/codeowners/CODEOWNERS.jsonnet: -------------------------------------------------------------------------------- 1 | function() ||| 2 | # Catch-all code owner 3 | * @RadxaYuntian 4 | 5 | # Disown CI yaml so automerge can work 6 | # https://github.com/orgs/community/discussions/23064#discussioncomment-8383923 7 | .github/actions/**/*.yaml 8 | .github/workflows/*.yaml 9 | ||| 10 | -------------------------------------------------------------------------------- /src/share/rsdk/common/dependabot/dependabot.yaml.jsonnet: -------------------------------------------------------------------------------- 1 | function() std.manifestYamlDoc( 2 | { 3 | version: 2, 4 | updates: [{ 5 | "package-ecosystem": "github-actions", 6 | directory: "/", 7 | schedule: { 8 | interval: "daily" 9 | } 10 | }] 11 | }, 12 | quote_keys=false 13 | ) 14 | -------------------------------------------------------------------------------- /src/share/rsdk/common/dependabot/workflow.jsonnet: -------------------------------------------------------------------------------- 1 | function() std.manifestYamlDoc( 2 | { 3 | name: "Dependabot auto-merge", 4 | on: { 5 | pull_request: {}, 6 | }, 7 | permissions: { 8 | contents: "write", 9 | "pull-requests": "write", 10 | }, 11 | jobs: { 12 | dependabot: { 13 | "runs-on": "ubuntu-latest", 14 | "if": "github.actor == 'dependabot[bot]'", 15 | steps: [ 16 | { 17 | name: "Dependabot metadata", 18 | id: "metadata", 19 | uses: "dependabot/fetch-metadata@v2", 20 | with: { 21 | "github-token": "${{ secrets.GITHUB_TOKEN }}", 22 | }, 23 | }, 24 | { 25 | name: "Approve a PR & Enable auto-merge for Dependabot PRs", 26 | run: ||| 27 | gh pr review --approve "$PR_URL" 28 | gh pr merge --auto --merge "$PR_URL" 29 | |||, 30 | env: { 31 | PR_URL: "${{github.event.pull_request.html_url}}", 32 | GH_TOKEN: "${{secrets.GITHUB_TOKEN}}", 33 | }, 34 | }, 35 | ], 36 | }, 37 | }, 38 | }, 39 | quote_keys=false, 40 | ) 41 | -------------------------------------------------------------------------------- /src/share/rsdk/common/repo_rulesets/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 4398694, 3 | "name": "default", 4 | "target": "branch", 5 | "source_type": "Repository", 6 | "source": "radxa-pkg/linux-rk2410-nocsf", 7 | "enforcement": "active", 8 | "conditions": { 9 | "ref_name": { 10 | "exclude": [], 11 | "include": [ 12 | "~DEFAULT_BRANCH" 13 | ] 14 | } 15 | }, 16 | "rules": [ 17 | { 18 | "type": "deletion" 19 | }, 20 | { 21 | "type": "non_fast_forward" 22 | }, 23 | { 24 | "type": "merge_queue", 25 | "parameters": { 26 | "merge_method": "REBASE", 27 | "max_entries_to_build": 5, 28 | "min_entries_to_merge": 1, 29 | "max_entries_to_merge": 5, 30 | "min_entries_to_merge_wait_minutes": 5, 31 | "grouping_strategy": "HEADGREEN", 32 | "check_response_timeout_minutes": 120 33 | } 34 | }, 35 | { 36 | "type": "required_linear_history" 37 | }, 38 | { 39 | "type": "pull_request", 40 | "parameters": { 41 | "required_approving_review_count": 1, 42 | "dismiss_stale_reviews_on_push": true, 43 | "require_code_owner_review": true, 44 | "require_last_push_approval": false, 45 | "required_review_thread_resolution": true, 46 | "automatic_copilot_code_review_enabled": false, 47 | "allowed_merge_methods": [ 48 | "rebase" 49 | ] 50 | } 51 | }, 52 | { 53 | "type": "required_status_checks", 54 | "parameters": { 55 | "strict_required_status_checks_policy": false, 56 | "do_not_enforce_on_create": false, 57 | "required_status_checks": [ 58 | { 59 | "context": "build", 60 | "integration_id": 15368 61 | } 62 | ] 63 | } 64 | } 65 | ], 66 | "bypass_actors": [ 67 | { 68 | "actor_id": null, 69 | "actor_type": "OrganizationAdmin", 70 | "bypass_mode": "always" 71 | }, 72 | { 73 | "actor_id": 5, 74 | "actor_type": "RepositoryRole", 75 | "bypass_mode": "always" 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /src/share/rsdk/configs/distributions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "distribution": "debian", 4 | "suites": [ 5 | "buster", 6 | "bullseye", 7 | "bookworm", 8 | "trixie", 9 | "sid" 10 | ], 11 | "supported_suites": [ 12 | "bullseye", 13 | "bookworm", 14 | "sid" 15 | ] 16 | }, 17 | { 18 | "distribution": "ubuntu", 19 | "suites": [ 20 | "focal", 21 | "jammy", 22 | "noble" 23 | ], 24 | "supported_suites": [ 25 | "jammy", 26 | "noble" 27 | ] 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/distro_check.libjsonnet: -------------------------------------------------------------------------------- 1 | local distro_list = import "distributions.json"; 2 | 3 | function(suite) 4 | std.filter(function(x) std.member(x.suites, suite), 5 | distro_list)[0].distribution 6 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/product_data.libjsonnet: -------------------------------------------------------------------------------- 1 | local product_list = import "products.json"; 2 | 3 | function(product) 4 | std.filter(function(x) x.product == product, 5 | product_list)[0] 6 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/product_firmware_type.libjsonnet: -------------------------------------------------------------------------------- 1 | local product_soc = import "product_soc.libjsonnet"; 2 | local soc_list = import "socs.json"; 3 | 4 | function(product) 5 | std.filter(function(x) std.member(x.soc_list, product_soc(product)), 6 | soc_list)[0].firmware_type 7 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/product_partition_table_type.libjsonnet: -------------------------------------------------------------------------------- 1 | local product_soc = import "product_soc.libjsonnet"; 2 | local soc_list = import "socs.json"; 3 | 4 | function(product) 5 | std.filter(function(x) std.member(x.soc_list, product_soc(product)), 6 | soc_list)[0].partition_table_type 7 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/product_soc.libjsonnet: -------------------------------------------------------------------------------- 1 | local product_data = import "product_data.libjsonnet"; 2 | 3 | function(product) 4 | product_data(product).soc 5 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/rsdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "default_image_name": "output.img" 4 | }, 5 | "completions": { 6 | "supported_subcommands": [ 7 | "build", 8 | "chroot", 9 | "config", 10 | "devcon", 11 | "help", 12 | "infra-package-update", 13 | "infra-product-build", 14 | "infra-product-update", 15 | "infra-repo-build", 16 | "infra-repo-sync", 17 | "infra-repo-update", 18 | "install", 19 | "setup", 20 | "shell", 21 | "tui", 22 | "write-image" 23 | ] 24 | }, 25 | "infra": { 26 | "organizations": { 27 | "package": "radxa-pkg", 28 | "repository": "radxa-repo", 29 | "product": "radxa-build" 30 | }, 31 | "repository": { 32 | "keyrings": [ 33 | "4AEC337235A97EDD397E3DCD67A474DD40402951", 34 | "EF181314AFE1834694A34CC65D93177D0752732A" 35 | ], 36 | "origin": "Radxa", 37 | "label": "Freight" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/soc_family.libjsonnet: -------------------------------------------------------------------------------- 1 | local soc_list = import "socs.json"; 2 | 3 | function(soc) 4 | std.filter(function(x) std.member(x.soc_list, soc), 5 | soc_list)[0].soc_family 6 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/soc_specific_repo.libjsonnet: -------------------------------------------------------------------------------- 1 | local soc_list = import "socs.json"; 2 | 3 | function(soc) 4 | std.length(std.filter(function(x) std.member(x.soc_specific_repo, soc), 5 | soc_list)) > 0 6 | -------------------------------------------------------------------------------- /src/share/rsdk/configs/socs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "soc_family": "amlogic", 4 | "partition_table_type": "mbr", 5 | "firmware_type": "u-boot", 6 | "soc_list": [ 7 | "a311d", 8 | "s905y2" 9 | ], 10 | "soc_specific_repo": [] 11 | }, 12 | { 13 | "soc_family": "rockchip", 14 | "partition_table_type": "gpt", 15 | "firmware_type": "u-boot", 16 | "soc_list": [ 17 | "rk3308", 18 | "rk3308bs", 19 | "rk3328", 20 | "rk3399t", 21 | "rk3399", 22 | "op1", 23 | "rk3399pro", 24 | "rk3528", 25 | "rk3528a", 26 | "rk3562", 27 | "rk3566", 28 | "rk3566t", 29 | "rk3568", 30 | "rk3576", 31 | "rk3582", 32 | "rk3588s", 33 | "rk3588s2", 34 | "rk3588" 35 | ], 36 | "soc_specific_repo": [ 37 | "rk3566", 38 | "rk3566t", 39 | "rk3568", 40 | "rk3528a", 41 | "rk3576", 42 | "rk3582", 43 | "rk3588s2", 44 | "rk3588" 45 | ] 46 | }, 47 | { 48 | "soc_family": "cix", 49 | "partition_table_type": "gpt", 50 | "firmware_type": "edk2", 51 | "soc_list": [ 52 | "cd8180" 53 | ], 54 | "soc_specific_repo": [ 55 | "cd8180" 56 | ] 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.devcontainer/.devenv/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.devcontainer/.direnv/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "customizations": { 3 | "vscode": { 4 | "settings": { 5 | "terminal.integrated.defaultProfile.linux": "bash" 6 | }, 7 | "extensions": [ 8 | "mkhl.direnv", 9 | "github.vscode-github-actions", 10 | "grafana.vscode-jsonnet", 11 | "ms-vscode.makefile-tools", 12 | "vivaxy.vscode-conventional-commits" 13 | ] 14 | } 15 | }, 16 | "image": "mcr.microsoft.com/devcontainers/base:bookworm", 17 | "features": { 18 | "ghcr.io/devcontainers/features/nix:1": { 19 | "version": "latest", 20 | "packages": "cachix,direnv,devenv", 21 | "extraNixConfig": [ 22 | "experimental-features = nix-command flakes", 23 | // Uncomment below to speed up container building in China 24 | // "substituters = https://mirrors.ustc.edu.cn/nix-channels/store https://devenv.cachix.org https://cache.nixos.org", 25 | "trusted-users = root vscode" 26 | ] 27 | } 28 | }, 29 | "mounts": [ 30 | { 31 | "source": "${localWorkspaceFolder}/.devcontainer/.devenv", 32 | "target": "${containerWorkspaceFolder}/.devenv", 33 | "type": "bind" 34 | }, 35 | { 36 | "source": "${localWorkspaceFolder}/.devcontainer/.direnv", 37 | "target": "${containerWorkspaceFolder}/.direnv", 38 | "type": "bind" 39 | } 40 | ], 41 | "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind,consistency=cached", 42 | "runArgs": [ 43 | // https://github.com/moby/moby/issues/27195#issuecomment-1410745778 44 | "--ulimit", "nofile=1024:524288" 45 | ], 46 | "overrideCommand": true, 47 | "updateContentCommand": "make devcontainer_setup" 48 | } 49 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.envrc: -------------------------------------------------------------------------------- 1 | source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" 2 | 3 | use devenv -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.github/workflows/docs.yaml.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | ) std.manifestYamlDoc( 4 | { 5 | name: "Deploy documentation", 6 | on: { 7 | workflow_dispatch: {}, 8 | merge_group: {}, 9 | push: { 10 | branches: [ 11 | "main", 12 | ], 13 | paths: [ 14 | "docs/**", 15 | "theme/**", 16 | "po/**", 17 | "book.toml", 18 | ".github/workflows/docs.yaml", 19 | ], 20 | }, 21 | pull_request: { 22 | paths: [ 23 | "docs/**", 24 | "theme/**", 25 | "po/**", 26 | "book.toml", 27 | ".github/workflows/docs.yaml", 28 | ], 29 | }, 30 | }, 31 | permissions: {}, 32 | concurrency: { 33 | group: "${{ github.workflow }}-${{ github.ref }}", 34 | "cancel-in-progress": true, 35 | }, 36 | jobs: { 37 | build: { 38 | "runs-on": "ubuntu-latest", 39 | permissions: { 40 | pages: "write", 41 | "id-token": "write", 42 | }, 43 | steps: [ 44 | { 45 | name: "Checkout", 46 | uses: "actions/checkout@v4", 47 | with: { 48 | "fetch-depth": 0, 49 | }, 50 | }, 51 | { 52 | name: "Setup mdBook", 53 | uses: "peaceiris/actions-mdbook@v2", 54 | with: { 55 | "mdbook-version": "latest", 56 | }, 57 | }, 58 | { 59 | name: "Install mdbook plugins", 60 | shell: "bash", 61 | run: ||| 62 | plugins=( 63 | mdbook-admonish 64 | mdbook-linkcheck 65 | mdbook-i18n-helpers 66 | mdbook-toc 67 | mdbook-cmdrun 68 | ) 69 | for i in "${plugins[@]}" 70 | do 71 | cargo install "$i" 72 | done 73 | |||, 74 | }, 75 | { 76 | name: "Build", 77 | shell: "bash", 78 | run: ||| 79 | mdbook build 80 | for po_lang in zh-CN 81 | do 82 | POT_CREATION_DATE=$(grep --max-count 1 '^"POT-Creation-Date:' po/$po_lang.po | sed -E 's/".*: (.*)\\n"/\1/') 83 | if [[ $POT_CREATION_DATE == "" ]]; then 84 | POT_CREATION_DATE=now 85 | fi 86 | echo "::group::Building $po_lang translation as of $POT_CREATION_DATE" 87 | rm -r docs/ 88 | git restore --source "$(git rev-list -n 1 --before "$POT_CREATION_DATE" @)" docs/ 89 | # Set language and adjust site URL. Clear the redirects 90 | # since they are in sync with the source files, not the 91 | # translation. 92 | MDBOOK_BOOK__LANGUAGE=$po_lang \ 93 | MDBOOK_OUTPUT__HTML__SITE_URL=/%(target)s/$po_lang/ \ 94 | MDBOOK_OUTPUT__HTML__REDIRECT='{}' \ 95 | mdbook build -d book/$po_lang 96 | mv book/$po_lang/html book/html/$po_lang 97 | echo "::endgroup::" 98 | done 99 | ||| % {target: target}, 100 | }, 101 | { 102 | name: "Setup Pages", 103 | uses: "actions/configure-pages@v5", 104 | }, 105 | { 106 | name: "Upload artifact", 107 | uses: "actions/upload-pages-artifact@v3", 108 | with: { 109 | path: "./book/html", 110 | }, 111 | }, 112 | { 113 | name: "Deploy to GitHub Pages", 114 | uses: "actions/deploy-pages@v4", 115 | "if": "github.event_name != 'pull_request'", 116 | }, 117 | ], 118 | }, 119 | } 120 | }, 121 | quote_keys=false, 122 | ) 123 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.github/workflows/new_version.yaml.jsonnet: -------------------------------------------------------------------------------- 1 | function() std.manifestYamlDoc( 2 | { 3 | name: "Create release", 4 | "run-name": "${{ inputs.update && 'Update submodule' || '' }}${{ inputs.update && inputs.release && ' & ' || '' }}${{ inputs.release && 'Release new version' }}${{ !inputs.update && !inputs.release && 'Test for new release' || '' }}", 5 | on: { 6 | workflow_dispatch: { 7 | inputs: { 8 | update: { 9 | description: "Update submodule", 10 | type: "boolean", 11 | required: true, 12 | default: false, 13 | }, 14 | release: { 15 | description: "Release new version", 16 | type: "boolean", 17 | required: true, 18 | default: true, 19 | }, 20 | }, 21 | }, 22 | }, 23 | permissions: {}, 24 | jobs: { 25 | release: { 26 | "runs-on": "ubuntu-latest", 27 | permissions: { 28 | contents: "write", 29 | }, 30 | steps: [ 31 | { 32 | name: "Checkout", 33 | uses: "actions/checkout@v4", 34 | with: { 35 | "fetch-depth": 0, 36 | submodules: "recursive", 37 | token: "${{secrets.GIT_PUSH_TOKEN}}", 38 | }, 39 | }, 40 | { 41 | name: "Update submodules", 42 | "if": "github.event.inputs.update == 'true'", 43 | shell: "bash", 44 | run: ||| 45 | git config user.name "github-actions[bot]" 46 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 47 | git submodule update --remote 48 | if git diff --quiet; then 49 | echo "Submodules are the latest. Nothing to update." 50 | exit 51 | fi 52 | git add . 53 | git commit -m "chore: update submodules" 54 | |||, 55 | }, 56 | { 57 | name: "Set up QEMU Emulation", 58 | uses: "docker/setup-qemu-action@v3", 59 | with: { 60 | image: "tonistiigi/binfmt:latest", 61 | }, 62 | }, 63 | { 64 | name: "Test", 65 | uses: "devcontainers/ci@v0.3", 66 | with: { 67 | push: "never", 68 | runCmd: ||| 69 | sudo apt-get update 70 | sudo apt-get install --no-install-recommends -y git-buildpackage 71 | export DEBEMAIL="dev@radxa.com" 72 | export DEBFULLNAME='"Radxa Computer Co., Ltd"' 73 | git config user.name "github-actions[bot]" 74 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 75 | make dch 76 | make test deb 77 | |||, 78 | }, 79 | }, 80 | { 81 | name: "Push", 82 | "if": "github.event.inputs.release == 'true'", 83 | shell: "bash", 84 | run: ||| 85 | git push 86 | |||, 87 | }, 88 | ], 89 | }, 90 | } 91 | }, 92 | quote_keys=false, 93 | ) 94 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/.gitignore: -------------------------------------------------------------------------------- 1 | # Devenv 2 | /.devenv* 3 | /devenv.local.nix 4 | 5 | # direnv 6 | /.direnv 7 | 8 | # pre-commit 9 | /.pre-commit-config.yaml 10 | 11 | # Local VS Code configuration 12 | /.vscode* 13 | 14 | # Kernel build artifacts 15 | /*.deb 16 | /*.buildinfo 17 | /*.changes 18 | /.pc 19 | 20 | # Output folder 21 | /out 22 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/Makefile.linux.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | ) ||| 4 | -include .github/local/Makefile.local 5 | PROJECT ?= %(target)s 6 | 7 | KERNEL_FORK ?= %(fork)s 8 | ARCH ?= arm64 9 | CROSS_COMPILE ?= aarch64-linux-gnu- 10 | DPKG_FLAGS ?= -d 11 | KERNEL_DEFCONFIG ?= defconfig radxa.config 12 | CUSTOM_ENV_DEFINITIONS ?= 13 | CUSTOM_MAKE_DEFINITIONS ?= 14 | CUSTOM_DEBUILD_ENV ?= DEB_BUILD_OPTIONS='parallel=1' 15 | SUPPORT_CLEAN ?= true 16 | 17 | KMAKE ?= $(CUSTOM_ENV_DEFINITIONS) $(MAKE) -C "$(SRC-KERNEL)" -j$(shell nproc) \ 18 | $(CUSTOM_MAKE_DEFINITIONS) \ 19 | ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) HOSTCC=$(CROSS_COMPILE)gcc \ 20 | KDEB_COMPRESS="xz" KDEB_CHANGELOG_DIST="unstable" DPKG_FLAGS=$(DPKG_FLAGS) \ 21 | LOCALVERSION=-$(shell dpkg-parsechangelog -S Version | cut -d "-" -f 2)-$(KERNEL_FORK) \ 22 | KERNELRELEASE=$(shell dpkg-parsechangelog -S Version)-$(KERNEL_FORK) \ 23 | KDEB_PKGVERSION=$(shell dpkg-parsechangelog -S Version) 24 | 25 | .DEFAULT_GOAL := all 26 | .PHONY: all 27 | all: build 28 | 29 | .PHONY: devcontainer_setup 30 | devcontainer_setup: 31 | sudo dpkg --add-architecture arm64 32 | sudo apt-get update 33 | sudo apt-get build-dep . -y 34 | 35 | # 36 | # Test 37 | # 38 | .PHONY: test 39 | test: 40 | 41 | # 42 | # Build 43 | # 44 | .PHONY: build 45 | build: pre_build build-defconfig build-bindeb post_build 46 | 47 | .PHONY: pre_build 48 | pre_build: 49 | # Fix file permissions when created from template 50 | chmod +x debian/rules 51 | 52 | .PHONY: post_build 53 | post_build: 54 | 55 | SRC-KERNEL ?= src 56 | 57 | .PHONY: build-defconfig 58 | build-defconfig: $(SRC-KERNEL) 59 | $(KMAKE) $(KERNEL_DEFCONFIG) 60 | 61 | .PHONY: build-dtbs 62 | build-dtbs: $(SRC-KERNEL) 63 | $(KMAKE) dtbs 64 | 65 | .PHONY: build-modules 66 | build-modules: $(SRC-KERNEL) 67 | $(KMAKE) modules 68 | 69 | .PHONY: build-all 70 | build-all: $(SRC-KERNEL) 71 | $(KMAKE) all 72 | 73 | .PHONY: build-bindeb 74 | build-bindeb: $(SRC-KERNEL) build-all 75 | $(KMAKE) bindeb-pkg 76 | mv linux-*_arm64.deb linux-upstream*_arm64.changes linux-upstream*_arm64.buildinfo ../ 77 | 78 | # 79 | # Clean 80 | # 81 | .PHONY: distclean 82 | distclean: clean 83 | if [ "$(SUPPORT_CLEAN)" == "true" ]; then $(KMAKE) distclean; fi 84 | 85 | .PHONY: clean 86 | clean: clean-deb 87 | if [ "$(SUPPORT_CLEAN)" == "true" ]; then $(KMAKE) clean; fi 88 | 89 | .PHONY: clean-deb 90 | clean-deb: 91 | rm -rf debian/.debhelper debian/$(PROJECT)*/ debian/linux-*/ debian/tmp/ debian/debhelper-build-stamp debian/files debian/*.debhelper.log debian/*.*.debhelper debian/*.substvars 92 | rm -f linux-*_arm64.deb linux-upstream*_arm64.changes linux-upstream*_arm64.buildinfo 93 | 94 | # 95 | # Release 96 | # 97 | .PHONY: dch 98 | dch: debian/changelog 99 | gbp dch --ignore-branch --multimaint-merge --release --spawn-editor=never \ 100 | --git-log='--no-merges --perl-regexp --invert-grep --grep=^(chore:\stemplates\sgenerated)' \ 101 | --dch-opt=--upstream --commit --commit-msg="feat: release %%(version)s" 102 | 103 | .PHONY: deb 104 | deb: debian 105 | $(CUSTOM_DEBUILD_ENV) debuild --no-lintian --lintian-hook "lintian --fail-on error,warning --suppress-tags-from-file $(PWD)/debian/common-lintian-overrides -- %%p_%%v_*.changes" --no-sign -b 106 | 107 | .PHONY: release 108 | release: 109 | gh workflow run .github/workflows/new_version.yaml --ref $(shell git branch --show-current) 110 | ||| % { 111 | target: target, 112 | fork: std.splitLimit(target, "-", 1)[1], 113 | } 114 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/Makefile.u-boot.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | ) ||| 4 | -include .github/local/Makefile.local 5 | PROJECT ?= %(target)s 6 | 7 | UBOOT_FORK ?= %(fork)s 8 | ARCH ?= arm 9 | CROSS_COMPILE ?= aarch64-linux-gnu- 10 | CUSTOM_ENV_DEFINITIONS ?= 11 | CUSTOM_MAKE_DEFINITIONS ?= 12 | CUSTOM_DEBUILD_ENV ?= DEB_BUILD_OPTIONS='parallel=1' 13 | SUPPORT_CLEAN ?= true 14 | 15 | UMAKE ?= $(CUSTOM_ENV_DEFINITIONS) $(MAKE) -C "$(SRC-UBOOT)" -j$(shell nproc) \ 16 | $(CUSTOM_MAKE_DEFINITIONS) \ 17 | ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) \ 18 | UBOOTVERSION=$(shell dpkg-parsechangelog -S Version)-$(UBOOT_FORK) 19 | 20 | UBOOT_PRODUCTS ?= 21 | 22 | .DEFAULT_GOAL := all 23 | .PHONY: all 24 | all: build 25 | 26 | .PHONY: devcontainer_setup 27 | devcontainer_setup: 28 | sudo apt-get update 29 | sudo apt-get build-dep . -y 30 | 31 | # 32 | # Test 33 | # 34 | .PHONY: test 35 | test: 36 | 37 | # 38 | # Build 39 | # 40 | DIR-OUTPUT := out 41 | SRC-UBOOT := src 42 | 43 | $(DIR-OUTPUT): 44 | mkdir -p $@ 45 | 46 | .PHONY: build 47 | build: $(DIR-OUTPUT) $(SRC-UBOOT) pre_build $(UBOOT_PRODUCTS) post_build 48 | 49 | .PHONY: pre_build 50 | pre_build: 51 | # Fix file permissions when created from template 52 | chmod +x debian/rules 53 | 54 | .PHONY: post_build 55 | post_build: 56 | 57 | # 58 | # Clean 59 | # 60 | .PHONY: clean_config 61 | clean_config: 62 | rm -f $(SRC-UBOOT)/.config 63 | 64 | .PHONY: distclean 65 | distclean: clean 66 | if [ "$(SUPPORT_CLEAN)" == "true" ]; then $(UMAKE) distclean; fi 67 | 68 | .PHONY: clean 69 | clean: clean-deb 70 | if [ "$(SUPPORT_CLEAN)" == "true" ]; then $(UMAKE) clean; fi 71 | 72 | .PHONY: clean-deb 73 | clean-deb: 74 | rm -rf $(DIR-OUTPUT) debian/.debhelper debian/$(PROJECT)*/ debian/u-boot-*/ debian/tmp/ debian/debhelper-build-stamp debian/files debian/*.debhelper.log debian/*.*.debhelper debian/*.substvars 75 | 76 | # 77 | # Release 78 | # 79 | .PHONY: dch 80 | dch: debian/changelog 81 | gbp dch --ignore-branch --multimaint-merge --release --spawn-editor=never \ 82 | --git-log='--no-merges --perl-regexp --invert-grep --grep=^(chore:\stemplates\sgenerated)' \ 83 | --dch-opt=--upstream --commit --commit-msg="feat: release %%(version)s" 84 | 85 | .PHONY: deb 86 | deb: debian 87 | $(CUSTOM_DEBUILD_ENV) debuild --no-lintian --lintian-hook "lintian --fail-on error,warning --suppress-tags-from-file $(PWD)/debian/common-lintian-overrides -- %%p_%%v_*.changes" --no-sign -b 88 | 89 | .PHONY: release 90 | release: 91 | gh workflow run .github/workflows/new_version.yaml --ref $(shell git branch --show-current) 92 | ||| % { 93 | target: target, 94 | fork: std.splitLimit(target, "-", 1)[1], 95 | } 96 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/README.md.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | pkg_org, 4 | ) ||| 5 | # %(target)s 6 | 7 | [![Release](https://github.com/%(pkg_org)s/%(target)s/actions/workflows/release.yaml/badge.svg)](https://github.com/%(pkg_org)s/%(target)s/actions/workflows/release.yaml) 8 | 9 | ## Build 10 | 11 | 1. `git clone --recurse-submodules https://github.com/%(pkg_org)s/%(target)s.git` 12 | 2. Open in [`devcontainer`](https://code.visualstudio.com/docs/devcontainers/containers) 13 | 3. `make deb` 14 | ||| % { 15 | target: target, 16 | pkg_org: pkg_org, 17 | } 18 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/.gitignore: -------------------------------------------------------------------------------- 1 | /.debhelper 2 | /debhelper-build-stamp 3 | /files 4 | /linux-*/ 5 | /u-boot-*/ 6 | /*.debhelper.log 7 | /*.*.debhelper 8 | /*.substvars 9 | /tmp 10 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/changelog.jsonnet: -------------------------------------------------------------------------------- 1 | function(target) ||| 2 | %(target)s (0.1.0-1) UNRELEASED; urgency=medium 3 | 4 | * Add initial Debian packaging support 5 | 6 | -- "Radxa Computer Co., Ltd" Thu, 01 Jan 1970 08:00:00 +0800 7 | ||| % { 8 | target: target, 9 | } 10 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/common-lintian-overrides: -------------------------------------------------------------------------------- 1 | # We do not track this on GitHub 2 | initial-upload-closes-no-bugs 3 | 4 | # We might use our own distribution name 5 | bad-distribution-in-changes-file 6 | 7 | # Our package is built on GitHub-hosted runner, 8 | # which uses Ubuntu, and will default to zstd compression. 9 | # This was not supported in Debian 11. 10 | custom-compression-in-debian-rules 11 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/compat: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/control.linux.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | ) ||| 4 | Source: %(target)s 5 | Maintainer: "Radxa Computer Co., Ltd" 6 | Section: admin 7 | Priority: standard 8 | Standards-Version: 4.6.0 9 | Build-Depends: debhelper (>=12~), 10 | devscripts, 11 | lintian, 12 | dh-exec, 13 | flex, 14 | bison, 15 | bc, 16 | libncurses-dev, 17 | crossbuild-essential-arm64 [!arm64], 18 | binfmt-support [!arm64], 19 | qemu-user-static [!arm64], 20 | libc6:arm64 [!arm64], 21 | libssl-dev:arm64, 22 | cpio, 23 | kmod:arm64, 24 | libyaml-dev:arm64, 25 | rsync, 26 | 27 | Package: linux-image 28 | Architecture: all 29 | Section: kernel 30 | Priority: optional 31 | Provides: linux-image 32 | Depends: radxa-overlays-dkms, 33 | linux-image-${binary:Version}-%(fork)s, 34 | ${misc:Depends}, 35 | Description: Radxa Linux meta-package for new product 36 | This is the meta-package for Linux kernel. 37 | 38 | Package: linux-headers 39 | Architecture: all 40 | Section: kernel 41 | Priority: optional 42 | Provides: linux-headers 43 | Depends: linux-headers-${binary:Version}-%(fork)s, 44 | ${misc:Depends}, 45 | Description: Radxa Linux headers meta-package for new product 46 | This is the meta-package for Linux headers. 47 | 48 | Package: linux-libc-dev 49 | Architecture: all 50 | Section: kernel 51 | Priority: optional 52 | Provides: linux-libc-dev 53 | Depends: linux-libc-dev-${binary:Version}-%(fork)s, 54 | ${misc:Depends}, 55 | Description: Radxa Linux libc-dev meta-package for new product 56 | This is the meta-package for Linux libc-dev. 57 | ||| % { 58 | target: target, 59 | fork: std.splitLimit(target, "-", 1)[1], 60 | } 61 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/control.u-boot.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | ) ||| 4 | Source: %(target)s 5 | Maintainer: "Radxa Computer Co., Ltd" 6 | Section: admin 7 | Priority: standard 8 | Standards-Version: 4.6.0 9 | Build-Depends: debhelper (>=12~), 10 | devscripts, 11 | lintian, 12 | dh-exec, 13 | flex, 14 | bison, 15 | python3-setuptools, 16 | swig, 17 | python3-dev, 18 | libgnutls28-dev, 19 | python3-pyelftools, 20 | libncurses-dev, 21 | crossbuild-essential-arm64 [!arm64], 22 | crossbuild-essential-armhf [!armhf], 23 | crossbuild-essential-armel [!armel], 24 | xxd, 25 | bc, 26 | lib32stdc++6 [!i386], 27 | lib32z1 [!i386], 28 | dos2unix, 29 | 30 | Package: %(target)s 31 | Architecture: all 32 | Section: admin 33 | Priority: optional 34 | Depends: ${misc:Depends}, 35 | Description: U-Boot based on %(fork)s 36 | This package provides the prebuilt U-Boot based on %(fork)s. 37 | 38 | Package: u-boot-product 39 | Architecture: all 40 | Depends: %(target)s, 41 | ${misc:Depends}, 42 | Section: admin 43 | Priority: optional 44 | Description: Radxa U-Boot meta-package for new product. 45 | This package provides the prebuilt U-Boot for new product. 46 | 47 | ||| % { 48 | target: target, 49 | fork: std.splitLimit(target, "-", 1)[1], 50 | } 51 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/copyright.jsonnet: -------------------------------------------------------------------------------- 1 | function(target) ||| 2 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 3 | Upstream-Name: %(target)s 4 | Source: https://github.com/radxa-pkg/%(target)s 5 | 6 | Files: * 7 | Copyright: © 2025 Radxa Computer Co., Ltd 8 | License: GPL-3+ 9 | 10 | License: GPL-3+ 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 3, or (at your option) 14 | any later version. 15 | . 16 | This program is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | General Public License for more details. 20 | . 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 24 | 02110-1301, USA. 25 | . 26 | On Debian systems, the complete text of the GNU General Public License 27 | can be found in /usr/share/common-licenses/GPL-3. 28 | ||| % { 29 | target: target, 30 | } -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/patches/series.linux: -------------------------------------------------------------------------------- 1 | linux/0001-feat-Radxa-common-kernel-config.patch 2 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | include /usr/share/dpkg/pkg-info.mk 4 | include /usr/share/dpkg/architecture.mk 5 | -include .github/local/rules.local 6 | 7 | %: 8 | dh $@ 9 | 10 | override_dh_builddeb: 11 | dh_builddeb -- -Zxz 12 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/debian/u-boot.install: -------------------------------------------------------------------------------- 1 | out/* usr/lib/u-boot/ -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/devenv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devenv": { 4 | "locked": { 5 | "dir": "src/modules", 6 | "lastModified": 1734951937, 7 | "owner": "cachix", 8 | "repo": "devenv", 9 | "rev": "4b8677f62022e6a235cc4e93a6bbc3d57b77817f", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "dir": "src/modules", 14 | "owner": "cachix", 15 | "repo": "devenv", 16 | "type": "github" 17 | } 18 | }, 19 | "flake-compat": { 20 | "flake": false, 21 | "locked": { 22 | "lastModified": 1733328505, 23 | "owner": "edolstra", 24 | "repo": "flake-compat", 25 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "edolstra", 30 | "repo": "flake-compat", 31 | "type": "github" 32 | } 33 | }, 34 | "git-hooks": { 35 | "inputs": { 36 | "flake-compat": "flake-compat", 37 | "gitignore": "gitignore", 38 | "nixpkgs": [ 39 | "nixpkgs" 40 | ] 41 | }, 42 | "locked": { 43 | "lastModified": 1742649964, 44 | "owner": "cachix", 45 | "repo": "git-hooks.nix", 46 | "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "cachix", 51 | "repo": "git-hooks.nix", 52 | "type": "github" 53 | } 54 | }, 55 | "gitignore": { 56 | "inputs": { 57 | "nixpkgs": [ 58 | "git-hooks", 59 | "nixpkgs" 60 | ] 61 | }, 62 | "locked": { 63 | "lastModified": 1709087332, 64 | "owner": "hercules-ci", 65 | "repo": "gitignore.nix", 66 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 67 | "type": "github" 68 | }, 69 | "original": { 70 | "owner": "hercules-ci", 71 | "repo": "gitignore.nix", 72 | "type": "github" 73 | } 74 | }, 75 | "nixpkgs": { 76 | "locked": { 77 | "lastModified": 1733477122, 78 | "owner": "cachix", 79 | "repo": "devenv-nixpkgs", 80 | "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "cachix", 85 | "ref": "rolling", 86 | "repo": "devenv-nixpkgs", 87 | "type": "github" 88 | } 89 | }, 90 | "root": { 91 | "inputs": { 92 | "devenv": "devenv", 93 | "git-hooks": "git-hooks", 94 | "nixpkgs": "nixpkgs", 95 | "pre-commit-hooks": [ 96 | "git-hooks" 97 | ] 98 | } 99 | } 100 | }, 101 | "root": "root", 102 | "version": 7 103 | } 104 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/devenv.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | 3 | { 4 | imports = lib.optional (builtins.pathExists ./.github/local/devenv.nix) ./.github/local/devenv.nix; 5 | 6 | # https://devenv.sh/packages/ 7 | packages = with pkgs; [ 8 | bash-completion 9 | mdbook 10 | mdbook-admonish 11 | mdbook-cmdrun 12 | mdbook-i18n-helpers 13 | mdbook-linkcheck 14 | mdbook-toc 15 | ncurses 16 | ]; 17 | 18 | pre-commit = { 19 | hooks = { 20 | commitizen.enable = true; 21 | shellcheck = { 22 | enable = true; 23 | entry = lib.mkForce "${pkgs.shellcheck}/bin/shellcheck -x"; 24 | }; 25 | shfmt.enable = true; 26 | statix.enable = true; 27 | typos = { 28 | enable = true; 29 | excludes = [ 30 | "theme/highlight.js" 31 | ]; 32 | settings.ignored-words = [ 33 | "Synopsys" 34 | "HSI" 35 | ]; 36 | }; 37 | }; 38 | }; 39 | 40 | starship.enable = true; 41 | } 42 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-package/template.jsonnet: -------------------------------------------------------------------------------- 1 | local LICENSE = import "../common/licenses/GPLv3.jsonnet"; 2 | local CODEOWNERS = import "../common/codeowners/CODEOWNERS.jsonnet"; 3 | local dependabot_yaml = import "../common/dependabot/dependabot.yaml.jsonnet"; 4 | local dependabot_workflow = import "../common/dependabot/workflow.jsonnet"; 5 | local check_linked_issue_yaml = import "../common/check_linked_issue/check_linked_issue.yaml.jsonnet"; 6 | local docs_yaml = import ".github/workflows/docs.yaml.jsonnet"; 7 | local new_version_yaml = import ".github/workflows/new_version.yaml.jsonnet"; 8 | local release_yaml = import ".github/workflows/release.yaml.jsonnet"; 9 | local copyright = import "debian/copyright.jsonnet"; 10 | local README_md = import "README.md.jsonnet"; 11 | local Makefile_linux = import "Makefile.linux.jsonnet"; 12 | local Makefile_u_boot = import "Makefile.u-boot.jsonnet"; 13 | local changelog = import "debian/changelog.jsonnet"; 14 | local control_linux = import "debian/control.linux.jsonnet"; 15 | local control_u_boot = import "debian/control.u-boot.jsonnet"; 16 | 17 | function( 18 | target, 19 | build_org, 20 | repo_org, 21 | pkg_org, 22 | git_rev, 23 | new_repo, 24 | ) { 25 | "LICENSE": LICENSE(), 26 | ".devcontainer/.devenv/.gitignore": importstr ".devcontainer/.devenv/.gitignore", 27 | ".devcontainer/.direnv/.gitignore": importstr ".devcontainer/.direnv/.gitignore", 28 | ".devcontainer/devcontainer.json": importstr ".devcontainer/devcontainer.json", 29 | ".github/dependabot.yaml": dependabot_yaml(), 30 | ".github/workflows/dependabot.yaml": dependabot_workflow(), 31 | ".github/workflows/docs.yaml": docs_yaml(target), 32 | ".github/workflows/new_version.yaml": new_version_yaml(), 33 | ".github/workflows/release.yaml": release_yaml(), 34 | ".github/workflows/check_linked_issue.yaml": check_linked_issue_yaml(), 35 | "debian/compat": importstr "debian/compat", 36 | "debian/copyright": copyright(target), 37 | "debian/rules": importstr "debian/rules", 38 | "debian/common-lintian-overrides": importstr "debian/common-lintian-overrides", 39 | ".envrc": importstr ".envrc", 40 | "devenv.lock": importstr "devenv.lock", 41 | "devenv.nix": importstr "devenv.nix", 42 | "README.md": README_md(target, pkg_org), 43 | } + (if new_repo == true 44 | then 45 | { 46 | "debian/.gitignore": importstr "debian/.gitignore", 47 | "debian/changelog": changelog(target), 48 | "debian/source/format": importstr "debian/source/format", 49 | ".github/CODEOWNERS": CODEOWNERS(), 50 | ".gitignore": importstr ".gitignore", 51 | } 52 | else 53 | {} 54 | ) + (if std.startsWith(target, "linux") 55 | then 56 | { 57 | "debian/patches/linux/0001-feat-Radxa-common-kernel-config.patch": importstr "debian/patches/linux/0001-feat-Radxa-common-kernel-config.patch", 58 | "Makefile": Makefile_linux(target), 59 | } + (if new_repo == true 60 | then 61 | { 62 | "debian/patches/series": importstr "debian/patches/series.linux", 63 | "debian/control": control_linux(target), 64 | } 65 | else 66 | {} 67 | ) 68 | else if std.startsWith(target, "u-boot") 69 | then 70 | { 71 | "Makefile": Makefile_u_boot(target), 72 | } + (if new_repo == true 73 | then 74 | { 75 | "debian/u-boot.install": importstr "debian/u-boot.install", 76 | "debian/control": control_u_boot(target), 77 | } 78 | else 79 | {} 80 | ) 81 | else 82 | {} 83 | ) 84 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-product/.github/workflows/workflow.jsonnet: -------------------------------------------------------------------------------- 1 | local product_data = import "../../../configs/product_data.libjsonnet"; 2 | 3 | local release_info = function(variant) if variant == "release" 4 | then 5 | { 6 | name: "b${{ github.run_number }} (rsdk)", 7 | tag_name: "rsdk-b${{ github.run_number }}", 8 | body_path: "README.md", 9 | } 10 | else if variant == "test" 11 | then 12 | { 13 | name: "t${{ github.run_number }} (rsdk)", 14 | tag_name: "rsdk-t${{ github.run_number }}", 15 | body: "This is a test build for internal development.\nOnly use when specifically instructed by Radxa support.\n", 16 | } 17 | else 18 | {}; 19 | 20 | function( 21 | target, 22 | variant, 23 | ) std.manifestYamlDoc( 24 | { 25 | name: "Build image for %(variant)s channel" % {variant: variant}, 26 | on: { 27 | workflow_dispatch: {} 28 | }, 29 | env: { 30 | GH_TOKEN: "${{ github.token }}" 31 | }, 32 | jobs: { 33 | prepare_release: { 34 | "runs-on": "ubuntu-latest", 35 | steps: [ 36 | { 37 | name: "Checkout", 38 | uses: "actions/checkout@v4", 39 | with: { 40 | "fetch-depth": 0, 41 | "fetch-tags": true, 42 | }, 43 | }, 44 | { 45 | name: "Check for existing releases", 46 | run: ||| 47 | TAG="%(tag_name)s" 48 | if git show-ref --tags --verify --quiet "refs/tags/${TAG}"; then 49 | echo "Release ${TAG} exists." 50 | exit 1 51 | fi 52 | ||| % {tag_name: release_info(variant).tag_name}, 53 | }, 54 | { 55 | name: "Generate changelog", 56 | uses: "radxa-repo/rbuild-changelog@main", 57 | with: { 58 | product: target 59 | } 60 | }, 61 | { 62 | name: "Query product info", 63 | id: "query", 64 | uses: "RadxaOS-SDK/rsdk/.github/actions/query@main", 65 | with: { 66 | product: target 67 | } 68 | }, 69 | { 70 | name: "Create empty release", 71 | id: "release", 72 | uses: "softprops/action-gh-release@v2", 73 | with: { 74 | token: "${{ secrets.GITHUB_TOKEN }}", 75 | target_commitish: "main", 76 | draft: false, 77 | prerelease: true, 78 | files: ".changelog/changelog.md", 79 | } + release_info(variant), 80 | } 81 | ], 82 | outputs: { 83 | release_id: "${{ steps.release.outputs.id }}", 84 | suites: "${{ steps.query.outputs.suites }}", 85 | editions: "${{ steps.query.outputs.editions }}", 86 | } 87 | }, 88 | build: { 89 | "runs-on": "ubuntu-22.04", 90 | needs: "prepare_release", 91 | strategy: { 92 | matrix: { 93 | product: [ target ], 94 | suite: "${{ fromJSON(needs.prepare_release.outputs.suites )}}", 95 | edition: "${{ fromJSON(needs.prepare_release.outputs.editions )}}", 96 | } 97 | }, 98 | steps: [ 99 | { 100 | name: "Checkout", 101 | uses: "actions/checkout@v4", 102 | }, 103 | { 104 | name: "Build image", 105 | uses: "RadxaOS-SDK/rsdk/.github/actions/build@main", 106 | with: { 107 | product: "${{ matrix.product }}", 108 | suite: "${{ matrix.suite }}", 109 | edition: "${{ matrix.edition }}", 110 | "release-id": "${{ needs.prepare_release.outputs.release_id }}", 111 | "github-token": "${{ secrets.GITHUB_TOKEN }}", 112 | } + if variant == "test" 113 | then 114 | { 115 | "test-repo": true, 116 | timestamp: "t${{ github.run_number }}", 117 | tag_name: release_info(variant).tag_name, 118 | } 119 | else 120 | {}, 121 | } 122 | ] 123 | } 124 | } 125 | }, 126 | quote_keys=false, 127 | ) 128 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-product/README.md.jsonnet: -------------------------------------------------------------------------------- 1 | local product_data = import "../configs/product_data.libjsonnet"; 2 | 3 | function( 4 | target, 5 | build_org, 6 | ) ||| 7 | # %(product_full_name)s 8 | [![Build image for Release channel](https://github.com/%(build_org)s/%(product)s/actions/workflows/build.yaml/badge.svg)](https://github.com/%(build_org)s/%(product)s/actions/workflows/build.yaml) [![Build image for Test channel](https://github.com/%(build_org)s/%(product)s/actions/workflows/test.yaml/badge.svg)](https://github.com/%(build_org)s/%(product)s/actions/workflows/test.yaml) 9 | 10 | ## What is this? 11 | 12 | This repo is the central location for Radxa-built system images for %(product_full_name)s. 13 | 14 | ## Which image should I use? 15 | 16 | For most systems, Radxa now only supports the Debian Desktop image. 17 | 18 | Other variants that were previously provided AS-IS are no longer provided. Interested users need to build those by themselves. 19 | 20 | Please also always use [the latest release](https://github.com/%(build_org)s/%(product)s/releases/latest) instead of any pre-release / test builds. Those will not be supported. 21 | 22 | ## Where is the source code? 23 | 24 | This repository is only for hosting the GitHub workflows that build the image. As such, you will need to examine the workflow to find the builder. 25 | 26 | ## Help! Something doesn't work! 27 | 28 | For other questions, please first take a look at [our Documentation](https://docs.radxa.com), which covers the most basic usages. 29 | 30 | Should you have any additional questions, please visit [our forum](https://forum.radxa.com/) or [our Discord](https://rock.sh/go), and we are willing to help. 31 | ||| % { 32 | product: product_data(target).product, 33 | product_full_name: product_data(target).product_full_name, 34 | build_org: build_org 35 | } 36 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-product/template.jsonnet: -------------------------------------------------------------------------------- 1 | local LICENSE = import "../common/licenses/GPLv3.jsonnet"; 2 | local CODEOWNERS = import "../common/codeowners/CODEOWNERS.jsonnet"; 3 | local dependabot_yaml = import "../common/dependabot/dependabot.yaml.jsonnet"; 4 | local dependabot_workflow = import "../common/dependabot/workflow.jsonnet"; 5 | local check_linked_issue_yaml = import "../common/check_linked_issue/check_linked_issue.yaml.jsonnet"; 6 | local README_md = import "README.md.jsonnet"; 7 | local workflow = import ".github/workflows/workflow.jsonnet"; 8 | 9 | function( 10 | target, 11 | build_org, 12 | repo_org, 13 | pkg_org, 14 | git_rev, 15 | new_repo, 16 | ) { 17 | "LICENSE": LICENSE(), 18 | "README.md": README_md(target, build_org), 19 | ".github/CODEOWNERS": CODEOWNERS(), 20 | ".github/dependabot.yaml": dependabot_yaml(), 21 | ".github/workflows/build.yaml": workflow(target, "release"), 22 | ".github/workflows/test.yaml": workflow(target, "test"), 23 | ".github/workflows/dependabot.yaml": dependabot_workflow(), 24 | ".github/workflows/check_linked_issue.yaml": check_linked_issue_yaml(), 25 | } 26 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-repo/.github/workflows/update.yaml.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | git_rev, 3 | ) std.manifestYamlDoc( 4 | { 5 | name: "Update package version info", 6 | on: { 7 | repository_dispatch: { 8 | types: [ 9 | "new_package_release" 10 | ], 11 | }, 12 | workflow_dispatch: {}, 13 | }, 14 | permissions: {}, 15 | concurrency: { 16 | group: "${{ github.workflow }}-${{ github.ref }}", 17 | "cancel-in-progress": true, 18 | }, 19 | jobs: { 20 | update: { 21 | "runs-on": "ubuntu-latest", 22 | permissions: { 23 | contents: "write", // for git push 24 | }, 25 | steps: [ 26 | { 27 | name: "Secret tests", 28 | uses: "actions/github-script@v7", 29 | env: { 30 | SECRETS: "${{ toJSON(secrets) }}", 31 | }, 32 | with: { 33 | script: ||| 34 | const secrets = JSON.parse(process.env.SECRETS); 35 | if (secrets.GPG_KEY === undefined || secrets.RADXA_APT_KEY_2024 === undefined) { 36 | core.setFailed('Required secrets are unset!'); 37 | } 38 | |||, 39 | }, 40 | }, 41 | { 42 | name: "Checkout rsdk", 43 | uses: "actions/checkout@v4", 44 | with: { 45 | repository: "RadxaOS-SDK/rsdk", 46 | ref: "%(git_rev)s" % {git_rev: git_rev}, 47 | }, 48 | }, 49 | { 50 | name: "Checkout current repo", 51 | uses: "actions/checkout@v4", 52 | with: { 53 | path: ".infra-repo", 54 | token: "${{secrets.GIT_PUSH_TOKEN}}", 55 | }, 56 | }, 57 | { 58 | name: "Update pkgs.json", 59 | id: "build", 60 | shell: "bash", 61 | env: { 62 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}", 63 | }, 64 | run: ||| 65 | pushd .infra-repo 66 | if [[ "${{ github.repository }}" != *-test ]] && \ 67 | wget "https://raw.githubusercontent.com/${{ github.repository }}-test/main/pkgs.lock" -O pkgs.lock.new; then 68 | mv pkgs.lock.new pkgs.lock 69 | git add pkgs.lock 70 | fi 71 | 72 | ../src/bin/rsdk infra-pkg-snapshot 73 | git add pkgs.json 74 | 75 | if [[ -n "$(git status --porcelain)" ]]; then 76 | git config --global user.name 'github-actions[bot]' 77 | git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' 78 | git commit -m "chore: update package snapshot" 79 | fi 80 | popd 81 | |||, 82 | }, 83 | { 84 | name: "Commit package snapshot", 85 | shell: "bash", 86 | run: ||| 87 | pushd .infra-repo 88 | git push 89 | popd 90 | |||, 91 | }, 92 | ], 93 | }, 94 | }, 95 | }, 96 | quote_keys=false, 97 | ) 98 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-repo/README.md.jsonnet: -------------------------------------------------------------------------------- 1 | function( 2 | target, 3 | repo_org, 4 | pkg_org, 5 | ) ||| 6 | # %(target)s 7 | 8 | [![Update packages](https://github.com/%(repo_org)s/%(target)s/actions/workflows/update.yaml/badge.svg)](https://github.com/%(repo_org)s/%(target)s/actions/workflows/update.yaml) 9 | 10 | ## Content 11 | 12 | * [Published GitHub Releases](https://%(repo_org)s.github.io/%(target)s/pkgs.json) 13 | * [File index](https://%(repo_org)s.github.io/%(target)s/files.list) 14 | 15 | ## Report issues 16 | 17 | The issue list for this repository should be strictly related to the package repository service itself. 18 | If your issue is related to a specific package's usage, you should file issues under package's repository over at [`%(pkg_org)s`](https://github.com/%(pkg_org)s). 19 | 20 | ## Usage 21 | 22 | ```bash 23 | # Install signing keyring 24 | keyring="$(mktemp)" 25 | version="$(curl -L https://github.com/%(pkg_org)s/radxa-archive-keyring/releases/latest/download/VERSION)" 26 | curl -L --output "$keyring" "https://github.com/%(pkg_org)s/radxa-archive-keyring/releases/latest/download/radxa-archive-keyring_${version}_all.deb" 27 | sudo dpkg -i "$keyring" 28 | rm -f "$keyring" 29 | # Add apt package repo 30 | sudo tee /etc/apt/sources.list.d/70-radxa.list <<< "deb [signed-by=/usr/share/keyrings/radxa-archive-keyring.gpg] https://%(repo_org)s.github.io/%(target)s/ %(target)s main" 31 | sudo apt-get update 32 | ``` 33 | ||| % { 34 | target: target, 35 | repo_org: repo_org, 36 | pkg_org: pkg_org, 37 | } 38 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-repo/pkgs.lock.jsonnet: -------------------------------------------------------------------------------- 1 | function() std.manifestJson({ 2 | 3 | }) 4 | -------------------------------------------------------------------------------- /src/share/rsdk/infra-repo/template.jsonnet: -------------------------------------------------------------------------------- 1 | local LICENSE = import "../common/licenses/GPLv3.jsonnet"; 2 | local CODEOWNERS = import "../common/codeowners/CODEOWNERS.jsonnet"; 3 | local dependabot_yaml = import "../common/dependabot/dependabot.yaml.jsonnet"; 4 | local dependabot_workflow = import "../common/dependabot/workflow.jsonnet"; 5 | local check_linked_issue_yaml = import "../common/check_linked_issue/check_linked_issue.yaml.jsonnet"; 6 | local README_md = import "README.md.jsonnet"; 7 | local pkgs_lock = import "pkgs.lock.jsonnet"; 8 | local update_yaml = import ".github/workflows/update.yaml.jsonnet"; 9 | local build_yaml = import ".github/workflows/build.yaml.jsonnet"; 10 | 11 | function( 12 | target, 13 | build_org, 14 | repo_org, 15 | pkg_org, 16 | git_rev, 17 | new_repo, 18 | ) { 19 | "LICENSE": LICENSE(), 20 | "README.md": README_md(target, repo_org, pkg_org), 21 | //"pkgs.lock": pkgs_lock(), 22 | ".github/dependabot.yaml": dependabot_yaml(), 23 | ".github/CODEOWNERS": CODEOWNERS(), 24 | ".github/workflows/dependabot.yaml": dependabot_workflow(), 25 | ".github/workflows/update.yaml": update_yaml(git_rev), 26 | ".github/workflows/check_linked_issue.yaml": check_linked_issue_yaml(), 27 | ".github/workflows/build.yaml": build_yaml(target, pkg_org, git_rev), 28 | } 29 | -------------------------------------------------------------------------------- /theme/css/language-picker.css: -------------------------------------------------------------------------------- 1 | #language-list { 2 | left: auto; 3 | right: 10px; 4 | } 5 | 6 | [dir="rtl"] #language-list { 7 | left: 10px; 8 | right: auto; 9 | } 10 | 11 | #language-list a { 12 | color: inherit; 13 | } 14 | -------------------------------------------------------------------------------- /theme/css/print.css: -------------------------------------------------------------------------------- 1 | #sidebar, 2 | #menu-bar, 3 | .nav-chapters, 4 | .mobile-nav-chapters { 5 | display: none; 6 | } 7 | 8 | #page-wrapper.page-wrapper { 9 | transform: none; 10 | margin-left: 0px; 11 | overflow-y: initial; 12 | } 13 | 14 | #content { 15 | max-width: none; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | .page { 21 | overflow-y: initial; 22 | } 23 | 24 | code { 25 | background-color: #666666; 26 | border-radius: 5px; 27 | 28 | /* Force background to be printed in Chrome */ 29 | -webkit-print-color-adjust: exact; 30 | } 31 | 32 | pre > .buttons { 33 | z-index: 2; 34 | } 35 | 36 | a, 37 | a:visited, 38 | a:active, 39 | a:hover { 40 | color: #4183c4; 41 | text-decoration: none; 42 | } 43 | 44 | h1, 45 | h2, 46 | h3, 47 | h4, 48 | h5, 49 | h6 { 50 | page-break-inside: avoid; 51 | page-break-after: avoid; 52 | } 53 | 54 | pre, 55 | code { 56 | page-break-inside: avoid; 57 | white-space: pre-wrap; 58 | } 59 | 60 | .fa { 61 | display: none !important; 62 | } 63 | -------------------------------------------------------------------------------- /theme/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/favicon.png -------------------------------------------------------------------------------- /theme/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /theme/fonts/SOURCE-CODE-PRO-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /theme/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ 2 | /* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ 3 | 4 | /* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 5 | @font-face { 6 | font-family: "Open Sans"; 7 | font-style: normal; 8 | font-weight: 300; 9 | src: 10 | local("Open Sans Light"), 11 | local("OpenSans-Light"), 12 | url("open-sans-v17-all-charsets-300.woff2") format("woff2"); 13 | } 14 | 15 | /* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 16 | @font-face { 17 | font-family: "Open Sans"; 18 | font-style: italic; 19 | font-weight: 300; 20 | src: 21 | local("Open Sans Light Italic"), 22 | local("OpenSans-LightItalic"), 23 | url("open-sans-v17-all-charsets-300italic.woff2") format("woff2"); 24 | } 25 | 26 | /* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 27 | @font-face { 28 | font-family: "Open Sans"; 29 | font-style: normal; 30 | font-weight: 400; 31 | src: 32 | local("Open Sans Regular"), 33 | local("OpenSans-Regular"), 34 | url("open-sans-v17-all-charsets-regular.woff2") format("woff2"); 35 | } 36 | 37 | /* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 38 | @font-face { 39 | font-family: "Open Sans"; 40 | font-style: italic; 41 | font-weight: 400; 42 | src: 43 | local("Open Sans Italic"), 44 | local("OpenSans-Italic"), 45 | url("open-sans-v17-all-charsets-italic.woff2") format("woff2"); 46 | } 47 | 48 | /* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 49 | @font-face { 50 | font-family: "Open Sans"; 51 | font-style: normal; 52 | font-weight: 600; 53 | src: 54 | local("Open Sans SemiBold"), 55 | local("OpenSans-SemiBold"), 56 | url("open-sans-v17-all-charsets-600.woff2") format("woff2"); 57 | } 58 | 59 | /* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 60 | @font-face { 61 | font-family: "Open Sans"; 62 | font-style: italic; 63 | font-weight: 600; 64 | src: 65 | local("Open Sans SemiBold Italic"), 66 | local("OpenSans-SemiBoldItalic"), 67 | url("open-sans-v17-all-charsets-600italic.woff2") format("woff2"); 68 | } 69 | 70 | /* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 71 | @font-face { 72 | font-family: "Open Sans"; 73 | font-style: normal; 74 | font-weight: 700; 75 | src: 76 | local("Open Sans Bold"), 77 | local("OpenSans-Bold"), 78 | url("open-sans-v17-all-charsets-700.woff2") format("woff2"); 79 | } 80 | 81 | /* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 82 | @font-face { 83 | font-family: "Open Sans"; 84 | font-style: italic; 85 | font-weight: 700; 86 | src: 87 | local("Open Sans Bold Italic"), 88 | local("OpenSans-BoldItalic"), 89 | url("open-sans-v17-all-charsets-700italic.woff2") format("woff2"); 90 | } 91 | 92 | /* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 93 | @font-face { 94 | font-family: "Open Sans"; 95 | font-style: normal; 96 | font-weight: 800; 97 | src: 98 | local("Open Sans ExtraBold"), 99 | local("OpenSans-ExtraBold"), 100 | url("open-sans-v17-all-charsets-800.woff2") format("woff2"); 101 | } 102 | 103 | /* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 104 | @font-face { 105 | font-family: "Open Sans"; 106 | font-style: italic; 107 | font-weight: 800; 108 | src: 109 | local("Open Sans ExtraBold Italic"), 110 | local("OpenSans-ExtraBoldItalic"), 111 | url("open-sans-v17-all-charsets-800italic.woff2") format("woff2"); 112 | } 113 | 114 | /* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ 115 | @font-face { 116 | font-family: "Source Code Pro"; 117 | font-style: normal; 118 | font-weight: 500; 119 | src: url("source-code-pro-v11-all-charsets-500.woff2") format("woff2"); 120 | } 121 | -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-300.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-300italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-600.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-600italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-700.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-700italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-800.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-800italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/open-sans-v17-all-charsets-regular.woff2 -------------------------------------------------------------------------------- /theme/fonts/source-code-pro-v11-all-charsets-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RadxaOS-SDK/rsdk/8d83948dc14fd6d48b57e10f8762b219b53cf3fb/theme/fonts/source-code-pro-v11-all-charsets-500.woff2 -------------------------------------------------------------------------------- /theme/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | * An increased contrast highlighting scheme loosely based on the 3 | * "Base16 Atelier Dune Light" theme by Bram de Haan 4 | * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) 5 | * Original Base16 color scheme by Chris Kempson 6 | * (https://github.com/chriskempson/base16) 7 | */ 8 | 9 | /* Comment */ 10 | .hljs-comment, 11 | .hljs-quote { 12 | color: #575757; 13 | } 14 | 15 | /* Red */ 16 | .hljs-variable, 17 | .hljs-template-variable, 18 | .hljs-attribute, 19 | .hljs-tag, 20 | .hljs-name, 21 | .hljs-regexp, 22 | .hljs-link, 23 | .hljs-name, 24 | .hljs-selector-id, 25 | .hljs-selector-class { 26 | color: #d70025; 27 | } 28 | 29 | /* Orange */ 30 | .hljs-number, 31 | .hljs-meta, 32 | .hljs-built_in, 33 | .hljs-builtin-name, 34 | .hljs-literal, 35 | .hljs-type, 36 | .hljs-params { 37 | color: #b21e00; 38 | } 39 | 40 | /* Green */ 41 | .hljs-string, 42 | .hljs-symbol, 43 | .hljs-bullet { 44 | color: #008200; 45 | } 46 | 47 | /* Blue */ 48 | .hljs-title, 49 | .hljs-section { 50 | color: #0030f2; 51 | } 52 | 53 | /* Purple */ 54 | .hljs-keyword, 55 | .hljs-selector-tag { 56 | color: #9d00ec; 57 | } 58 | 59 | .hljs { 60 | display: block; 61 | overflow-x: auto; 62 | background: #f6f7f6; 63 | color: #000; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | 74 | .hljs-addition { 75 | color: #22863a; 76 | background-color: #f0fff4; 77 | } 78 | 79 | .hljs-deletion { 80 | color: #b31d28; 81 | background-color: #ffeef0; 82 | } 83 | --------------------------------------------------------------------------------