diff --git a/src/rust/NOTES.md b/src/rust/NOTES.md index 1f01e6e52..df4159756 100644 --- a/src/rust/NOTES.md +++ b/src/rust/NOTES.md @@ -2,11 +2,7 @@ ## OS Support -This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux -and Mariner distributions with the `apt`, `yum`, `dnf`, `microdnf` and `tdnf` package manager installed. - - -**Note:** Alpine is not supported because the rustup-init binary requires glibc to run, but Alpine Linux does not include `glibc` -by default. Instead, it uses musl libc, which is not binary-compatible with glibc. +This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux, +Mariner and Alpine distributions with the `apt`, `yum`, `dnf`, `microdnf`, `tdnf` and `apk` package manager installed. `bash` is required to execute the `install.sh` script. diff --git a/src/rust/README.md b/src/rust/README.md index ef0bc2311..e4d0aa0af 100644 --- a/src/rust/README.md +++ b/src/rust/README.md @@ -32,12 +32,8 @@ Installs Rust, common Rust utilities, and their required dependencies ## OS Support -This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux -and Mariner distributions with the `apt`, `yum`, `dnf`, `microdnf` and `tdnf` package manager installed. - - -**Note:** Alpine is not supported because the rustup-init binary requires glibc to run, but Alpine Linux does not include `glibc` -by default. Instead, it uses musl libc, which is not binary-compatible with glibc. +This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux, +Mariner and Alpine distributions with the `apt`, `yum`, `dnf`, `microdnf`, `tdnf` and `apk` package manager installed. `bash` is required to execute the `install.sh` script. diff --git a/src/rust/install.sh b/src/rust/install.sh index 99a7ba8f5..fb7b77a05 100755 --- a/src/rust/install.sh +++ b/src/rust/install.sh @@ -58,8 +58,10 @@ elif command -v microdnf >/dev/null 2>&1; then PKG_MANAGER="microdnf" elif command -v tdnf >/dev/null 2>&1; then PKG_MANAGER="tdnf" +elif command -v apk >/dev/null 2>&1; then + PKG_MANAGER="apk" else - echo "No supported package manager found. Supported: apt, dnf, yum, microdnf, tdnf" + echo "No supported package manager found. Supported: apt, dnf, yum, microdnf, tdnf, apk" exit 1 fi @@ -85,6 +87,11 @@ clean_package_cache() { tdnf) tdnf clean all ;; + apk) + if [ "$(ls -1 /var/cache/apk/ 2>/dev/null | wc -l)" -gt 0 ]; then + rm -rf /var/cache/apk/* + fi + ;; esac } @@ -217,6 +224,12 @@ pkg_mgr_update() { tdnf) tdnf makecache || true ;; + apk) + if [ "$(find /var/cache/apk/* | wc -l)" = "0" ]; then + echo "Running apk update..." + apk update + fi + ;; esac } @@ -230,6 +243,9 @@ is_package_installed() { dnf|yum|microdnf|tdnf) rpm -q "$package" >/dev/null 2>&1 ;; + apk) + apk info --installed "$package" >/dev/null 2>&1 + ;; esac } @@ -266,6 +282,14 @@ check_packages() { "gnupg2") packages[$i]="gnupg" ;; esac ;; + apk) + case "${packages[$i]}" in + "libc6-dev") packages[$i]="libc-dev" ;; + "python3-minimal") packages[$i]="python3" ;; + "libpython3.*") packages[$i]="python3-dev" ;; + "gnupg2") packages[$i]="gnupg" ;; + esac + ;; esac done @@ -295,6 +319,9 @@ check_packages() { tdnf) tdnf install -y "${missing_packages[@]}" ;; + apk) + apk add --no-cache "${missing_packages[@]}" + ;; esac fi } @@ -317,6 +344,9 @@ case "$PKG_MANAGER" in check_packages python3 python3-devel || true # LLDB might not be available in Photon/Mariner ;; + apk) + check_packages lldb python3 python3-dev || true + ;; esac # Get architecture @@ -348,6 +378,11 @@ case ${download_architecture} in ;; esac +clibtype="gnu" +if ldd --version 2>&1 | grep -q 'musl'; then + clibtype="musl" +fi + # Install Rust umask 0002 if ! grep -e "^rustlang:" /etc/group > /dev/null 2>&1; then @@ -378,14 +413,14 @@ else fi echo "Installing Rust..." # Download and verify rustup sha - mkdir -p /tmp/rustup/target/${download_architecture}-unknown-linux-gnu/release/ - curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-gnu/rustup-init" -o /tmp/rustup/target/${download_architecture}-unknown-linux-gnu/release/rustup-init - curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-gnu/rustup-init.sha256" -o /tmp/rustup/rustup-init.sha256 + mkdir -p /tmp/rustup/target/${download_architecture}-unknown-linux-${clibtype}/release/ + curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-${clibtype}/rustup-init" -o /tmp/rustup/target/${download_architecture}-unknown-linux-${clibtype}/release/rustup-init + curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-${clibtype}/rustup-init.sha256" -o /tmp/rustup/rustup-init.sha256 cd /tmp/rustup - cp /tmp/rustup/target/${download_architecture}-unknown-linux-gnu/release/rustup-init /tmp/rustup/rustup-init + cp /tmp/rustup/target/${download_architecture}-unknown-linux-${clibtype}/release/rustup-init /tmp/rustup/rustup-init sha256sum -c rustup-init.sha256 - chmod +x target/${download_architecture}-unknown-linux-gnu/release/rustup-init - target/${download_architecture}-unknown-linux-gnu/release/rustup-init -y --no-modify-path --profile "${RUSTUP_PROFILE}" ${default_toolchain_arg} + chmod +x target/${download_architecture}-unknown-linux-${clibtype}/release/rustup-init + target/${download_architecture}-unknown-linux-${clibtype}/release/rustup-init -y --no-modify-path --profile "${RUSTUP_PROFILE}" ${default_toolchain_arg} cd ~ rm -rf /tmp/rustup fi diff --git a/test/rust/rust_with_alpine.sh b/test/rust/rust_with_alpine.sh new file mode 100644 index 000000000..d1315bc4d --- /dev/null +++ b/test/rust/rust_with_alpine.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Helper function to check component is installed +check_component_installed() { + local component=$1 + if rustup component list | grep -q "${component}.*installed"; then + return 0 # Component is installed (success) + else + return 1 # Component is not installed (failure) + fi +} + +# Definition specific tests +check "cargo version" cargo --version +check "rustc version" rustc --version +check "correct rust version" rustup target list | grep "aarch64-unknown-linux-musl.*installed" + +# Check that all specified extended components are installed +check "rust-analyzer is installed" check_component_installed "rust-analyzer" +check "rust-src is installed" check_component_installed "rust-src" +check "rustfmt is installed" check_component_installed "rustfmt" +check "clippy is installed" check_component_installed "clippy" +check "rust-docs is installed" check_component_installed "rust-docs" + +# Report result +reportResults + diff --git a/test/rust/scenarios.json b/test/rust/scenarios.json index 21e347947..a43d27566 100644 --- a/test/rust/scenarios.json +++ b/test/rust/scenarios.json @@ -64,14 +64,14 @@ "components": "" } } - }, + }, "rust_with_centos": { "image": "centos:centos7", "features": { "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -81,7 +81,7 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -91,7 +91,7 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -101,7 +101,7 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -111,7 +111,7 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -121,7 +121,7 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } }, @@ -131,8 +131,18 @@ "rust": { "version": "latest", "targets": "aarch64-unknown-linux-gnu", - "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" + } + } + }, + "rust_with_alpine": { + "image": "mcr.microsoft.com/devcontainers/base:alpine-3.21", + "features": { + "rust": { + "version": "latest", + "targets": "aarch64-unknown-linux-musl", + "components": "rust-analyzer,rust-src,rustfmt,clippy,rust-docs" } } - } -} + } +} \ No newline at end of file