diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 610574f80..b0ffeb2d8 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -54,6 +54,9 @@ jobs:
linux:
name: Linux
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ runtime: [ linux-x64, linux-arm64, linux-arm ]
steps:
- uses: actions/checkout@v4
@@ -67,7 +70,10 @@ jobs:
run: dotnet restore
- name: Build
- run: dotnet build --configuration LinuxRelease
+ run: |
+ dotnet build src/linux/Packaging.Linux/*.csproj \
+ --configuration=Release --no-self-contained \
+ --runtime=${{ matrix.runtime }}
- name: Test
run: |
@@ -82,7 +88,7 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
- name: linux-x64
+ name: ${{ matrix.runtime }}
path: |
artifacts
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3a2e708ca..1e020c425 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -232,6 +232,9 @@ jobs:
runs-on: ubuntu-latest
environment: release
needs: prereqs
+ strategy:
+ matrix:
+ runtime: [ linux-x64, linux-arm64, linux-arm ]
steps:
- uses: actions/checkout@v4
@@ -241,7 +244,10 @@ jobs:
dotnet-version: 8.0.x
- name: Build
- run: dotnet build --configuration=LinuxRelease
+ run: |
+ dotnet build src/linux/Packaging.Linux/*.csproj \
+ --configuration=LinuxRelease --no-self-contained \
+ --runtime=${{ matrix.runtime }}
- name: Run Linux unit tests
run: |
@@ -286,18 +292,18 @@ jobs:
run: |
# Sign Debian package
version=${{ needs.prereqs.outputs.version }}
- mv out/linux/Packaging.Linux/Release/deb/gcm-linux_amd64.$version.deb .
- debsigs --sign=origin --verify --check gcm-linux_amd64.$version.deb
+ mv out/linux/Packaging.Linux/Release/deb/gcm-${{ matrix.runtime }}.$version.deb .
+ debsigs --sign=origin --verify --check gcm-${{ matrix.runtime }}.$version.deb
# Generate tarball signature file
mv -v out/linux/Packaging.Linux/Release/tar/* .
- gpg --batch --yes --armor --output gcm-linux_amd64.$version.tar.gz.asc \
- --detach-sig gcm-linux_amd64.$version.tar.gz
+ gpg --batch --yes --armor --output gcm-${{ matrix.runtime }}.$version.tar.gz.asc \
+ --detach-sig gcm-${{ matrix.runtime }}.$version.tar.gz
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
- name: linux-artifacts
+ name: ${{ matrix.runtime }}-artifacts
path: |
./*.deb
./*.asc
@@ -466,9 +472,9 @@ jobs:
matrix:
component:
- os: ubuntu-latest
- artifact: linux-artifacts
+ artifact: linux-x64-artifacts
command: git-credential-manager
- description: linux
+ description: linux-x64
- os: macos-latest
artifact: macos-osx-x64-artifacts
command: git-credential-manager
@@ -510,15 +516,15 @@ jobs:
Start-Process -Wait -FilePath "$exePath" -ArgumentList "/SILENT /VERYSILENT /NORESTART"
}
- - name: Install Linux (Debian package)
- if: contains(matrix.component.description, 'linux')
+ - name: Install Linux x64 (Debian package)
+ if: contains(matrix.component.description, 'linux-x64')
run: |
debpath=$(find ./*.deb)
sudo apt install $debpath
"${{ matrix.component.command }}" configure
- - name: Install Linux (tarball)
- if: contains(matrix.component.description, 'linux')
+ - name: Install Linux x64 (tarball)
+ if: contains(matrix.component.description, 'linux-x64')
run: |
# Ensure we find only the source tarball, not the symbols
tarpath=$(find . -name '*[[:digit:]].tar.gz')
@@ -598,7 +604,9 @@ jobs:
az keyvault secret show --name "$GPG_PUBLIC_KEY_SECRET_NAME" \
--vault-name "$AZURE_VAULT" --query "value" \
| sed -e 's/^"//' -e 's/"$//' | base64 -d >gcm-public.asc
- mv gcm-public.asc linux-artifacts
+ cp gcm-public.asc linux-x64-artifacts/
+ cp gcm-public.asc linux-arm64-artifacts/
+ mv gcm-public.asc linux-arm-artifacts
- uses: actions/github-script@v7
with:
@@ -655,7 +663,9 @@ jobs:
uploadDirectoryToRelease('osx-payload-and-symbols'),
// Upload Linux artifacts
- uploadDirectoryToRelease('linux-artifacts'),
+ uploadDirectoryToRelease('linux-x64-artifacts'),
+ uploadDirectoryToRelease('linux-arm64-artifacts'),
+ uploadDirectoryToRelease('linux-arm-artifacts'),
// Upload .NET tool package
uploadDirectoryToRelease('dotnet-tool-sign'),
diff --git a/README.md b/README.md
index 18c9b1309..6c6aa1535 100644
--- a/README.md
+++ b/README.md
@@ -47,8 +47,8 @@ Basic HTTP authentication support|✓|✓|✓
Proxy support|✓|✓|✓
`amd64` support|✓|✓|✓
`x86` support|✓|_N/A_|✗
-`arm64` support|best effort|✓|best effort, no packages
-`armhf` support|_N/A_|_N/A_|best effort, no packages
+`arm64` support|best effort|✓|✓
+`armhf` support|_N/A_|_N/A_|✓
(\*) GCM guarantees support only for [the Linux distributions that are officially
supported by dotnet][dotnet-distributions].
diff --git a/docs/development.md b/docs/development.md
index 7729556f9..0242d68b8 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -54,6 +54,12 @@ To build from the command line, run:
dotnet build -c LinuxDebug
```
+If you want to build for a specific architecture, you can provide `linux-x64` or `linux-arm64` or `linux-arm` as the runtime:
+
+```shell
+dotnet build -c LinuxDebug -r linux-arm64
+```
+
You can find a copy of the Debian package (.deb) file in `out/linux/Packaging.Linux/deb/Debug`.
The flat binaries can also be found in `out/linux/Packaging.Linux/payload/Debug`.
diff --git a/src/linux/Packaging.Linux/Packaging.Linux.csproj b/src/linux/Packaging.Linux/Packaging.Linux.csproj
index 8b9755c78..ddfb31500 100644
--- a/src/linux/Packaging.Linux/Packaging.Linux.csproj
+++ b/src/linux/Packaging.Linux/Packaging.Linux.csproj
@@ -24,8 +24,8 @@
-
-
+
+
diff --git a/src/linux/Packaging.Linux/build.sh b/src/linux/Packaging.Linux/build.sh
index 9db7ad5e3..88f1b0359 100755
--- a/src/linux/Packaging.Linux/build.sh
+++ b/src/linux/Packaging.Linux/build.sh
@@ -30,6 +30,10 @@ case "$i" in
INSTALL_FROM_SOURCE="${i#*=}"
shift # past argument=value
;;
+ --runtime=*)
+ RUNTIME="${i#*=}"
+ shift # past argument=value
+ ;;
--install-prefix=*)
INSTALL_PREFIX="${i#*=}"
shift # past argument=value
@@ -45,6 +49,28 @@ if [ ! -d "$INSTALL_PREFIX" ]; then
mkdir -p "$INSTALL_PREFIX"
fi
+# Fall back to host architecture if no explicit runtime is given.
+if test -z "$RUNTIME"; then
+ HOST_ARCH="`dpkg-architecture -q DEB_HOST_ARCH`"
+
+ case $HOST_ARCH in
+ amd64)
+ RUNTIME="linux-x64"
+ ;;
+ arm64)
+ RUNTIME="linux-arm64"
+ ;;
+ armhf)
+ RUNTIME="linux-arm"
+ ;;
+ *)
+ die "Could not determine host architecture!"
+ ;;
+ esac
+fi
+
+echo "Building for runtime ${RUNTIME}"
+
# Perform pre-execution checks
CONFIGURATION="${CONFIGURATION:=Debug}"
if [ -z "$VERSION" ]; then
@@ -56,7 +82,7 @@ PAYLOAD="$OUTDIR/payload"
SYMBOLS="$OUTDIR/payload.sym"
# Lay out payload
-"$INSTALLER_SRC/layout.sh" --configuration="$CONFIGURATION" || exit 1
+"$INSTALLER_SRC/layout.sh" --configuration="$CONFIGURATION" --runtime="$RUNTIME" || exit 1
if [ $INSTALL_FROM_SOURCE = true ]; then
echo "Installing to $INSTALL_PREFIX"
@@ -79,7 +105,7 @@ if [ $INSTALL_FROM_SOURCE = true ]; then
echo "Install complete."
else
# Pack
- "$INSTALLER_SRC/pack.sh" --configuration="$CONFIGURATION" --payload="$PAYLOAD" --symbols="$SYMBOLS" --version="$VERSION" || exit 1
+ "$INSTALLER_SRC/pack.sh" --configuration="$CONFIGURATION" --runtime="$RUNTIME" --payload="$PAYLOAD" --symbols="$SYMBOLS" --version="$VERSION" || exit 1
fi
echo "Build of Packaging.Linux complete."
diff --git a/src/linux/Packaging.Linux/layout.sh b/src/linux/Packaging.Linux/layout.sh
index 6679c39ca..9355eaa02 100755
--- a/src/linux/Packaging.Linux/layout.sh
+++ b/src/linux/Packaging.Linux/layout.sh
@@ -23,6 +23,10 @@ case "$i" in
CONFIGURATION="${i#*=}"
shift # past argument=value
;;
+ --runtime=*)
+ RUNTIME="${i#*=}"
+ shift # past argument=value
+ ;;
*)
# unknown option
;;
@@ -39,7 +43,10 @@ PROJ_OUT="$OUT/linux/Packaging.Linux"
# Build parameters
FRAMEWORK=net8.0
-RUNTIME=linux-x64
+
+if [ -z "$RUNTIME" ]; then
+ die "--runtime was not set"
+fi
# Perform pre-execution checks
CONFIGURATION="${CONFIGURATION:=Debug}"
diff --git a/src/linux/Packaging.Linux/pack.sh b/src/linux/Packaging.Linux/pack.sh
index 14d26aee5..817704f76 100755
--- a/src/linux/Packaging.Linux/pack.sh
+++ b/src/linux/Packaging.Linux/pack.sh
@@ -28,6 +28,10 @@ case "$i" in
SYMBOLS="${i#*=}"
shift # past argument=value
;;
+ --runtime=*)
+ RUNTIME="${i#*=}"
+ shift # past argument=value
+ ;;
--configuration=*)
CONFIGURATION="${i#*=}"
shift # past argument=value
@@ -51,20 +55,17 @@ fi
if [ -z "$SYMBOLS" ]; then
die "--symbols was not set"
fi
-
-ARCH="`dpkg-architecture -q DEB_HOST_ARCH`"
-
-if test -z "$ARCH"; then
- die "Could not determine host architecture!"
+if [ -z "$RUNTIME" ]; then
+ die "--runtime was not set"
fi
TAROUT="$PROJ_OUT/$CONFIGURATION/tar/"
-TARBALL="$TAROUT/gcm-linux_$ARCH.$VERSION.tar.gz"
-SYMTARBALL="$TAROUT/gcm-linux_$ARCH.$VERSION-symbols.tar.gz"
+TARBALL="$TAROUT/gcm-$RUNTIME.$VERSION.tar.gz"
+SYMTARBALL="$TAROUT/gcm-$RUNTIME.$VERSION-symbols.tar.gz"
DEBOUT="$PROJ_OUT/$CONFIGURATION/deb"
DEBROOT="$DEBOUT/root"
-DEBPKG="$DEBOUT/gcm-linux_$ARCH.$VERSION.deb"
+DEBPKG="$DEBOUT/gcm-$RUNTIME.$VERSION.deb"
mkdir -p "$DEBROOT"
# Set full read, write, execute permissions for owner and just read and execute permissions for group and other
@@ -99,6 +100,22 @@ INSTALL_TO="$DEBROOT/usr/local/share/gcm-core/"
LINK_TO="$DEBROOT/usr/local/bin/"
mkdir -p "$DEBROOT/DEBIAN" "$INSTALL_TO" "$LINK_TO" || exit 1
+# Determine architecture for debian control file from the runtime architecture
+case $RUNTIME in
+ linux-x64)
+ ARCH="amd64"
+ ;;
+ linux-arm64)
+ ARCH="arm64"
+ ;;
+ linux-arm)
+ ARCH="armhf"
+ ;;
+ *)
+ die "Incompatible runtime architecture given for pack.sh"
+ ;;
+esac
+
# make the debian control file
# this is purposefully not indented, see
# https://stackoverflow.com/questions/9349616/bash-eof-in-if-statement
diff --git a/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj b/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj
index 2b594e3eb..456adf547 100644
--- a/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj
+++ b/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj
@@ -4,7 +4,7 @@
Exe
net8.0
net472;net8.0
- win-x86;osx-x64;linux-x64;osx-arm64
+ win-x86;osx-x64;linux-x64;osx-arm64;linux-arm64;linux-arm
x86
git-credential-manager
GitCredentialManager