Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/rust/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
8 changes: 2 additions & 6 deletions src/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
49 changes: 42 additions & 7 deletions src/rust/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
}

Expand Down Expand Up @@ -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
}

Expand All @@ -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
}

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -295,6 +319,9 @@ check_packages() {
tdnf)
tdnf install -y "${missing_packages[@]}"
;;
apk)
apk add --no-cache "${missing_packages[@]}"
;;
esac
fi
}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions test/rust/rust_with_alpine.sh
Original file line number Diff line number Diff line change
@@ -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

30 changes: 20 additions & 10 deletions test/rust/scenarios.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please also add a test case for alpine 3.22?

Copy link
Contributor Author

@olivierlemasle olivierlemasle Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • mcr.microsoft.com/devcontainers/base:alpine-3.22 has not yet been released.
  • alpine:3.22 is released but does not include bash, which is required for this feature.

What do you suggest, please?

Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
},
Expand All @@ -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"
}
}
},
Expand All @@ -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"
}
}
},
Expand All @@ -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"
}
}
},
Expand All @@ -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"
}
}
},
Expand All @@ -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"
}
}
},
Expand All @@ -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"
}
}
}
}
}
}