├── .gitignore ├── README.md ├── LICENSE ├── AppImage ├── Makefile ├── srb2 │ └── build.sh ├── appstream │ └── build.sh └── hexchat │ └── build.sh └── .github └── workflows └── build.yml /.gitignore: -------------------------------------------------------------------------------- 1 | *_source.tar.bz2 2 | *.AppDir 3 | *.AppImage 4 | out/ 5 | witchery-compose 6 | squashfs-root/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alpine to AppImage 2 | 3 | Converts Alpine Linux packages to AppImages using Docker, make, [witchery-compose](https://github.com/witchery-project/witchery/), and [go-appimage](https://github.com/probonopd/go-appimage). 4 | 5 | ## Pros 6 | 7 | * Relatively straightforward 8 | * The resulting AppImages should be able to run on glibc-based and on musl libc-based Linux distributions, even if they are _older_ than the distribution on which the binaries were compiled (Alpine edge) 9 | * Since the ingredients come from Alpine and use musl libc, they do not rely on the target system's glibc version 10 | 11 | ## Cons 12 | 13 | * AppImages created in this way may introduce _some_ overhead which could be optimized away by hand-crafting the AppImage instead of relying on [witchery-compose](https://github.com/witchery-project/witchery/) - however this could be mitigated by removing potentially unneeded files using additional `rm` commands 14 | 15 | ## Credits 16 | 17 | * [__xordspar0__](https://github.com/xordspar0) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017, 2019-2020 Jordan Christiansen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /AppImage/Makefile: -------------------------------------------------------------------------------- 1 | DOCKER=docker 2 | 3 | .PHONY: appimage 4 | appimage: witchery-compose appimagetool.AppImage 5 | @:$(if $(PACKAGE),,$(error PACKAGE is not set)) 6 | sudo rm -rf "${PACKAGE}/out" 7 | mkdir -p "${PACKAGE}/out" 8 | $(DOCKER) run \ 9 | --workdir /src \ 10 | --volume "${PWD}/${PACKAGE}:/src" \ 11 | --volume "${PWD}/${PACKAGE}/out:/out" \ 12 | --volume "${PWD}/:/tools" \ 13 | --env SRC_DIR=/src \ 14 | --env OUT_DIR=/out \ 15 | --env TOOLS_DIR=/tools \ 16 | --env PACKAGE="${PACKAGE}" \ 17 | --rm \ 18 | alpine:edge sh -ex /src/build.sh 19 | 20 | witchery-compose: 21 | wget https://raw.githubusercontent.com/witchery-project/witchery/refs/heads/master/witchery-compose 22 | chmod +x witchery-compose 23 | 24 | appimagetool.AppImage: 25 | wget -q https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous -O - \ 26 | | grep "appimagetool-.*-$$(uname -m).AppImage" \ 27 | | head -n 1 \ 28 | | cut -d '"' -f 2 \ 29 | | xargs -I url wget "https://github.com/url" -O appimagetool.AppImage 30 | chmod +x appimagetool.AppImage 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | inputs: 9 | package: 10 | description: 'Package name (e.g. appstream)' 11 | required: false 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 2 # So we can diff against the previous commit 21 | 22 | - name: Determine package; fall back to appstream 23 | id: determine-package 24 | run: | 25 | CHANGED_DIR=$(git diff --name-only HEAD~1 | grep ^AppImage/ | cut -d / -f 2 | sort | uniq | head -n 1) 26 | echo "Changed directory, using as package name: $CHANGED_DIR" 27 | if [ -z "$CHANGED_DIR" ]; then 28 | echo "::set-output name=package::appstream" 29 | else 30 | echo "::set-output name=package::$CHANGED_DIR" 31 | fi 32 | 33 | - name: Create AppImage from Alpine 34 | run: | 35 | cd AppImage/ 36 | # Echo the package name to the console 37 | echo "Building AppImage for ${{ github.event.inputs.package || steps.determine-package.outputs.package }}" 38 | make PACKAGE=${{ github.event.inputs.package || steps.determine-package.outputs.package }} 39 | 40 | - name: Upload artifacts 41 | uses: actions/upload-artifact@v4 42 | with: 43 | name: appimage 44 | path: AppImage/${{ github.event.inputs.package || steps.determine-package.outputs.package }}/out/*.AppImage 45 | -------------------------------------------------------------------------------- /AppImage/srb2/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eux 3 | 4 | [ -z "${PACKAGE}" ] && exit 1 5 | 6 | export VERSION=$(apk --no-cache -X https://dl-cdn.alpinelinux.org/alpine/edge/testing list "$PACKAGE" | grep -v fetch | cut -d- -f2) 7 | export ARCH=$(uname -m) 8 | 9 | src_dir=${SRC_DIR:-/src} 10 | out_dir=${OUT_DIR:-/out} 11 | tools_dir=${TOOLS_DIR:-/tools} 12 | appdir="$out_dir"/"$PACKAGE".AppDir 13 | 14 | apk update && apk add file rdfind 15 | 16 | "$tools_dir"/witchery-compose \ 17 | -k /etc/apk/keys \ 18 | -X https://dl-cdn.alpinelinux.org/alpine/edge/main \ 19 | -X https://dl-cdn.alpinelinux.org/alpine/edge/community \ 20 | -X https://dl-cdn.alpinelinux.org/alpine/edge/testing \ 21 | -d "$PACKAGE" \ 22 | -d mesa-gl \ 23 | -d mesa-egl \ 24 | -d libx11 \ 25 | -d libxext \ 26 | -d libxi \ 27 | -d alsa-lib \ 28 | -d alsa-plugins \ 29 | -d alsa-plugins-pulse \ 30 | "$appdir" 31 | 32 | chmod 755 "$appdir" 33 | 34 | ############################################ 35 | 36 | sed -i 's/Icon=.*/Icon=srb2/' "$appdir"/usr/share/applications/srb2.desktop 37 | sed -i 's/Exec=.*/Exec=srb2/' "$appdir"/usr/share/applications/srb2.desktop 38 | ln -s usr/share/pixmaps/srb2.png "$appdir"/srb2.png 39 | 40 | ############################################ 41 | 42 | export APPIMAGE_EXTRACT_AND_RUN=1 43 | "$tools_dir"/appimagetool.AppImage -s deploy "$appdir"/usr/share/applications/"$PACKAGE".desktop 44 | 45 | ############################################ 46 | 47 | sed -i '2a export SRB2WADDIR=${SRB2WADDIR:-share/games/SRB2}' "$appdir"/AppRun 48 | 49 | ############################################ 50 | 51 | rdfind -makesymlinks true . # Replace duplicate files with symlinks 52 | 53 | "$tools_dir"/appimagetool.AppImage "$appdir" 54 | mv *.AppImage "$out_dir"/ 55 | -------------------------------------------------------------------------------- /AppImage/appstream/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eux 3 | 4 | [ -z "${PACKAGE}" ] && exit 1 5 | 6 | export VERSION=$(apk --no-cache -X https://dl-cdn.alpinelinux.org/alpine/edge/testing list "$PACKAGE" | grep -v fetch | cut -d- -f2) 7 | export ARCH=$(uname -m) 8 | 9 | src_dir=${SRC_DIR:-/src} 10 | out_dir=${OUT_DIR:-/out} 11 | tools_dir=${TOOLS_DIR:-/tools} 12 | appdir="$out_dir"/"$PACKAGE".AppDir 13 | 14 | apk update && apk add file rdfind 15 | 16 | "$tools_dir"/witchery-compose \ 17 | -k /etc/apk/keys \ 18 | -X https://dl-cdn.alpinelinux.org/alpine/edge/main \ 19 | -X https://dl-cdn.alpinelinux.org/alpine/edge/community \ 20 | -X https://dl-cdn.alpinelinux.org/alpine/edge/testing \ 21 | -d "$PACKAGE" \ 22 | "$appdir" 23 | 24 | chmod 755 "$appdir" 25 | 26 | ############################################ 27 | 28 | mkdir -p "$appdir"/usr/share/applications/ 29 | cat > "$appdir"/usr/share/applications/appstreamcli.desktop <<\EOF 30 | [Desktop Entry] 31 | Type=Application 32 | Name=appstreamcli 33 | Comment=Tool to validate AppStream metadata on the command line 34 | Exec=appstreamcli 35 | Icon=appstreamcli 36 | Categories=Utility; 37 | Terminal=true 38 | EOF 39 | 40 | mkdir -p "$appdir"/usr/share/pixmaps/ 41 | wget https://github.com/ximion/appstream/raw/main/docs/images/src/png/appstream-logo.png -O "$appdir"/usr/share/pixmaps/appstreamcli.png 42 | 43 | ln -s usr/share/pixmaps/appstreamcli.png "$appdir"/appstreamcli.png 44 | 45 | # Remove extraneous symlinks (to busybox) 46 | find "$appdir"/usr/bin/ -type l -delete 47 | 48 | # Remove extraneous binaries and directories 49 | rm -rf "$appdir"/bin/ 50 | rm -rf "$appdir"/sbin/ 51 | find "$appdir"/usr/bin/ -type f -not -name 'appstreamcli' -delete 52 | rm -rf "$appdir"/usr/sbin/ 53 | rm -rf "$appdir"/usr/libexec/ 54 | rm -rf "$appdir"/usr/share/udhcpc 55 | rm -rf "$appdir"/etc/ 56 | rm -rf "$appdir"/dev/ 57 | rm -rf "$appdir"/var/ 58 | rm -rf "$appdir"/proc/ 59 | rm -rf "$appdir"/tmp/ 60 | 61 | ############################################ 62 | 63 | export APPIMAGE_EXTRACT_AND_RUN=1 64 | "$tools_dir"/appimagetool.AppImage -s deploy "$appdir"/usr/share/applications/appstreamcli.desktop 65 | 66 | ############################################ 67 | 68 | # No post-post-processing needed for this application 69 | 70 | ############################################ 71 | 72 | rdfind -makesymlinks true . # Replace duplicate files with symlinks 73 | 74 | "$tools_dir"/appimagetool.AppImage "$appdir" 75 | mv *.AppImage "$out_dir"/ -------------------------------------------------------------------------------- /AppImage/hexchat/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eux 3 | 4 | [ -z "${PACKAGE}" ] && exit 1 5 | 6 | export VERSION=$(apk --no-cache -X https://dl-cdn.alpinelinux.org/alpine/edge/testing list "$PACKAGE" | grep -v fetch | cut -d- -f2) 7 | export ARCH=$(uname -m) 8 | 9 | src_dir=${SRC_DIR:-/src} 10 | out_dir=${OUT_DIR:-/out} 11 | tools_dir=${TOOLS_DIR:-/tools} 12 | appdir="$out_dir"/"$PACKAGE".AppDir 13 | 14 | apk update && apk add file rdfind 15 | 16 | "$tools_dir"/witchery-compose \ 17 | -k /etc/apk/keys \ 18 | -X https://dl-cdn.alpinelinux.org/alpine/edge/main \ 19 | -X https://dl-cdn.alpinelinux.org/alpine/edge/community \ 20 | -X https://dl-cdn.alpinelinux.org/alpine/edge/testing \ 21 | -d "$PACKAGE" \ 22 | "$appdir" 23 | 24 | chmod 755 "$appdir" 25 | 26 | ############################################ 27 | 28 | find "$appdir" || true 29 | 30 | # Parsing svg is a pain for AppImage thumbnailers, hence use png 31 | # ImageMagick even fails to convert the svg, hence we have to grab a png from their website 32 | apk add imagemagick 33 | wget -q "https://avatars.githubusercontent.com/u/1938483?s=200&v=4" -O hexchat.png 34 | magick hexchat.png -resize 128@ "$appdir"/usr/share/icons/hicolor/128x128/apps/io.github.Hexchat.png 35 | cp "$appdir"/usr/share/icons/hicolor/128x128/apps/io.github.Hexchat.png . 36 | rm hexchat.png 37 | 38 | ############################################ 39 | 40 | # Remove extraneous symlinks (to busybox) 41 | find "$appdir"/usr/bin/ -type l -delete 42 | 43 | # Remove extraneous binaries and directories 44 | rm -rf "$appdir"/bin/ 45 | rm -rf "$appdir"/sbin/ 46 | find "$appdir"/usr/bin/ -type f -not -name "$PACKAGE" -delete # FIXME: It would be better not have those installed in the first place... 47 | rm -rf "$appdir"/usr/sbin/ 48 | rm -rf "$appdir"/usr/libexec/ 49 | rm -rf "$appdir"/usr/share/udhcpc 50 | rm -rf "$appdir"/etc/ 51 | rm -rf "$appdir"/dev/ 52 | rm -rf "$appdir"/var/ 53 | rm -rf "$appdir"/proc/ 54 | rm -rf "$appdir"/tmp/ 55 | 56 | ############################################ 57 | 58 | export APPIMAGE_EXTRACT_AND_RUN=1 59 | "$tools_dir"/appimagetool.AppImage -s deploy "$appdir"/usr/share/applications/*.desktop 60 | 61 | ############################################ 62 | 63 | # No post-post-processing needed for this application 64 | 65 | ############################################ 66 | 67 | rdfind -makesymlinks true . # Replace duplicate files with symlinks 68 | 69 | "$tools_dir"/appimagetool.AppImage "$appdir" 70 | mv *.AppImage "$out_dir"/ 71 | --------------------------------------------------------------------------------