Repository: static-web-server/static-web-server (language: rust)

Issue:
Add Android targets support
**Is your feature request related to a problem? Please describe.**
The releases don't include a binary for Android. 

**Describe the solution you'd like**
To change the workflow yaml to include it 

**Describe alternatives you've considered**
My fork (https://github.com/denisidoro/static-web-server) includes it. I completely changed the yaml file to make it work, though. That's why I'm not submitting a pull request here: I suppose you'll want to add support for this with minimal changes. 

**Additional context**
The binary can be used in e.g. Termux

Add Android targets support
**Is your feature request related to a problem? Please describe.**
The releases don't include a binary for Android. 

**Describe the solution you'd like**
To change the workflow yaml to include it 

**Describe alternatives you've considered**
My fork (https://github.com/denisidoro/static-web-server) includes it. I completely changed the yaml file to make it work, though. That's why I'm not submitting a pull request here: I suppose you'll want to add support for this with minimal changes. 

**Additional context**
The binary can be used in e.g. Termux



Discussion / hints:
Why not. But it should be interesting if you can tell a bit about the use case here with a new Android target(s).
Also, it should be great to describe which Android targets are you interested in.
> use case

I use an old phone as a raspberry Pi-like device. It has an FTP server, DLNA server and HTTP server.

> targets

Mainly aarch64. armv7 would be a plus, for older devices. 
Why not. But it should be interesting if you can tell a bit about the use case here with a new Android target(s).
Also, it should be great to describe which Android targets are you interested in.
> use case

I use an old phone as a raspberry Pi-like device. It has an FTP server, DLNA server and HTTP server.

> targets

Mainly aarch64. armv7 would be a plus, for older devices. 

Fix patch:
diff --git a/.github/workflows/devel.yml b/.github/workflows/devel.yml
index f5765740..7da23973 100644
--- a/.github/workflows/devel.yml
+++ b/.github/workflows/devel.yml
@@ -40,6 +40,9 @@ jobs:
           - linux-arm-gnueabihf
           - linux-musl-armv6
           - linux-musl-armv7
+          # NOTE: looks like not supported by `listenfd` crate
+          # - linux-android-armv7
+          - linux-android-arm64
           - macos
           - macos-arm64
           - windows-msvc
@@ -95,6 +98,15 @@ jobs:
             os: ubuntu-20.04
             rust: stable
             target: armv7-unknown-linux-musleabihf
+          #  NOTE: looks like not supported by `listenfd` crate
+          # - build: linux-android-armv7
+          #   os: ubuntu-22.04
+          #   rust: stable
+          #   target: armv7-linux-androideabi
+          - build: linux-android-arm64
+            os: ubuntu-22.04
+            rust: stable
+            target: aarch64-linux-android
           - build: macos
             os: macos-11
             rust: stable
@@ -123,18 +135,28 @@ jobs:
     - name: Checkout repository
       uses: actions/checkout@v3
 
+    - name: Install Linux/BSD tools
+      if: ${{ !contains(matrix.os, 'windows') }}
+      run: ci/install-tools.sh --target=${{ matrix.target }}
+
     - name: Install Rust
       uses: dtolnay/rust-toolchain@stable
       with:
         toolchain: ${{ matrix.rust }}
         target: ${{ matrix.target }}
 
-    - name: Use Cross
-      if: matrix.target != ''
+    - name: Set up Cross
+      if: ${{ !contains(matrix.os, 'windows') && matrix.target != '' }}
       run: |
-        cargo install cross@^0.2
-        echo "CARGO_BIN=cross" >> $GITHUB_ENV
-        echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
+        # Use 'cargo.sh' script for Android targets only
+        if [[ "${{ matrix.build }}" == "linux-android-armv7" ]] || [[ "${{ matrix.build }}" == "linux-android-arm64" ]]; then
+          echo "CARGO_BIN=ci/cargo.sh" >> $GITHUB_ENV
+        else
+          cargo install cross@^0.2
+          echo "CARGO_BIN=cross" >> $GITHUB_ENV
+        fi
+
+        echo "TARGET_FLAGS=--target=${{ matrix.target }}" >> $GITHUB_ENV
         echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
 
     - name: Show command used for Cargo
@@ -143,18 +165,17 @@ jobs:
         echo "target flag is: ${{ env.TARGET_FLAGS }}"
         echo "target dir is: ${{ env.TARGET_DIR }}"
 
-    - name: aarch64 specific items
-      if: matrix.build == 'macos-arm64'
+    - name: Skip tests
+      if: ${{ contains(fromJSON('["macos-arm64", "linux-android-arm64", "linux-android-armv7"]'), matrix.build) }}
       run: |
         # Can't run tests: cross-compiling
-        echo "SKIP_TESTS=yes" >> $GITHUB_ENV
+        echo "SKIP_TESTS=--no-run" >> $GITHUB_ENV
 
     - name: Run tests
       shell: bash
-      if: env.SKIP_TESTS == ''
       run: |
         if [[ "${{ matrix.build }}" == "pinned" ]]; then unset CARGO_REGISTRIES_CRATES_IO_PROTOCOL; fi
-        ${{ env.CARGO_BIN }} test --verbose ${{ env.TARGET_FLAGS }}
+        ${{ env.CARGO_BIN }} test --verbose ${{ env.TARGET_FLAGS }} ${{ env.SKIP_TESTS }}
 
     - name: Run build
       shell: bash
diff --git a/.github/workflows/release.docker.yml b/.github/workflows/release.docker.yml
index 0ce510e9..d6f04a78 100644
--- a/.github/workflows/release.docker.yml
+++ b/.github/workflows/release.docker.yml
@@ -1,7 +1,8 @@
 name: release-docker
 on:
   release:
-    types: published
+    types:
+      - published
 
 jobs:
   docker-image-alpine:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2e3bddef..420beb1d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -60,6 +60,8 @@ jobs:
           - linux-arm-gnueabihf
           - linux-musl-armv6
           - linux-musl-armv7
+          # - linux-android-armv7
+          - linux-android-arm64
           - macos
           - macos-arm64
           - windows-msvc
@@ -103,6 +105,14 @@ jobs:
           os: ubuntu-20.04
           rust: stable
           target: armv7-unknown-linux-musleabihf
+        # - build: linux-android-armv7
+        #   os: ubuntu-22.04
+        #   rust: stable
+        #   target: armv7-linux-androideabi
+        - build: linux-android-arm64
+          os: ubuntu-22.04
+          rust: stable
+          target: aarch64-linux-android
         - build: macos
           os: macos-11
           rust: stable
@@ -134,18 +144,27 @@ jobs:
       with:
         fetch-depth: 1
 
+    - name: Install Linux/BSD tools
+      if: ${{ !contains(matrix.os, 'windows') }}
+      run: ci/install-tools.sh --target=${{ matrix.target }}
+
     - name: Install Rust
       uses: dtolnay/rust-toolchain@stable
       with:
         toolchain: ${{ matrix.rust }}
         target: ${{ matrix.target }}
 
-    - name: Use Cross
+    - name: Set up Cross
       shell: bash
       run: |
         if [ "${{ matrix.os }}" = "ubuntu-20.04" ]; then
-          cargo install cross@^0.2
-          echo "CARGO_BIN=cross" >> $GITHUB_ENV
+          # Use 'cargo.sh' script for Android targets only
+          if [[ "${{ matrix.build }}" == "linux-android-armv7" ]] || [[ "${{ matrix.build }}" == "linux-android-arm64" ]]; then
+            echo "CARGO_BIN=ci/cargo.sh" >> $GITHUB_ENV
+          else
+            cargo install cross@^0.2
+            echo "CARGO_BIN=cross" >> $GITHUB_ENV
+          fi
         fi
         echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
         echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
diff --git a/ci/cargo.sh b/ci/cargo.sh
new file mode 100755
index 00000000..8fc29563
--- /dev/null
+++ b/ci/cargo.sh
@@ -0,0 +1,61 @@
+# Adapted from https://github.com/briansmith/ring/blob/main/mk/cargo.sh
+
+set -eux -o pipefail
+
+# Avoid putting the Android tools in `$PATH` because there are tools in this
+# directory like `clang` that would conflict with the same-named tools that may
+# be needed to compile the build script, or to compile for other targets.
+if [ -n "${ANDROID_HOME-}" ]; then
+  # Keep the next line in sync with the corresponding line in install-build-tools.sh.
+  ndk_version=25.2.9519653
+  ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT:-${ANDROID_HOME}/ndk/$ndk_version}
+fi
+if [ -n "${ANDROID_NDK_ROOT-}" ]; then
+  android_tools=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin
+fi
+
+for arg in $*; do
+  case $arg in
+    --target=*)
+      target=${arg#*=}
+      ;;
+    *)
+      ;;
+  esac
+done
+
+case $target in
+  aarch64-linux-android)
+    export CC_aarch64_linux_android=$android_tools/aarch64-linux-android21-clang
+    export AR_aarch64_linux_android=$android_tools/llvm-ar
+    export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$android_tools/aarch64-linux-android21-clang
+    ;;
+  # aarch64-unknown-linux-gnu)
+  #   export CC_aarch64_unknown_linux_gnu=clang-$llvm_version
+  #   export AR_aarch64_unknown_linux_gnu=llvm-ar-$llvm_version
+  #   export CFLAGS_aarch64_unknown_linux_gnu="--sysroot=/usr/aarch64-linux-gnu"
+  #   export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
+  #   export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="$qemu_aarch64"
+  #   ;;
+  # aarch64-unknown-linux-musl)
+  #   export CC_aarch64_unknown_linux_musl=clang-$llvm_version
+  #   export AR_aarch64_unknown_linux_musl=llvm-ar-$llvm_version
+  #   export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="$rustflags_self_contained"
+  #   export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUNNER="$qemu_aarch64"
+  #   ;;
+  # arm-unknown-linux-gnueabihf)
+  #   export CC_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc
+  #   export AR_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc-ar
+  #   export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc
+  #   export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER="$qemu_arm"
+  #   ;;
+  armv7-linux-androideabi)
+    export CC_armv7_linux_androideabi=$android_tools/armv7a-linux-androideabi19-clang
+    export AR_armv7_linux_androideabi=$android_tools/llvm-ar
+    export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$android_tools/armv7a-linux-androideabi19-clang
+    ;;
+  *)
+  ;;
+esac
+
+cargo "$@"
diff --git a/ci/install-tools.sh b/ci/install-tools.sh
new file mode 100755
index 00000000..d1dee424
--- /dev/null
+++ b/ci/install-tools.sh
@@ -0,0 +1,36 @@
+# Adapted from https://github.com/briansmith/ring/blob/main/mk/install-build-tools.sh
+
+set -eux -o pipefail
+
+target=$1
+
+case $target in
+--target*android*)
+  # https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html says
+  # "Going forward the Android platform will target the most recent LTS NDK,
+  # allowing Rust developers to access platform features sooner. These updates
+  # should occur yearly and will be announced in release notes." Assume that
+  # means that we should always prefer to be using the latest 25.x.y version of
+  # the NDK until the Rust project announces that we should use a higher major
+  # version number.
+  #
+  # TODO: This should probably be implemented as a map of Rust toolchain version
+  # to NDK version; e.g. our MSRV might (only) support an older NDK than the
+  # latest stable Rust toolchain.
+  #
+  # Keep the following line in sync with the corresponding line in cargo.sh.
+  ndk_version=25.2.9519653
+
+  mkdir -p "${ANDROID_HOME}/licenses"
+  android_license_file="${ANDROID_HOME}/licenses/android-sdk-license"
+  accept_android_license=24333f8a63b6825ea9c5514f83c2829b004d1fee
+  grep --quiet --no-messages "$accept_android_license" "$android_license_file" \
+    || echo $accept_android_license  >> "$android_license_file"
+  "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" "ndk;$ndk_version"
+
+  # XXX: Older Rust toolchain versions link with `-lgcc` instead of `-lunwind`;
+  # see https://github.com/rust-lang/rust/pull/85806.
+  find -L ${ANDROID_NDK_ROOT:-${ANDROID_HOME}/ndk/$ndk_version} -name libunwind.a \
+          -execdir sh -c 'echo "INPUT(-lunwind)" > libgcc.a' \;
+  ;;
+esac


Test patch: