Skip to content

Commit

Permalink
add support for Linux arm64 and Linux arm (#1633)
Browse files Browse the repository at this point in the history
Adds support for building and publishing Linux ARM64 and Linux ARM32
  • Loading branch information
mjcheetham authored Nov 6, 2024
2 parents 749e287 + 628acd0 commit 31ce754
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 32 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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: |
Expand All @@ -82,7 +88,7 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: linux-x64
name: ${{ matrix.runtime }}
path: |
artifacts
Expand Down
38 changes: 24 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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: |
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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'),
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down
6 changes: 6 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
4 changes: 2 additions & 2 deletions src/linux/Packaging.Linux/Packaging.Linux.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<Target Name="CoreCompile" Condition="'$(OSPlatform)'=='linux'">
<Message Text="$(MSBuildProjectDirectory)\build.sh --install-from-source=$(InstallFromSource) --configuration='$(Configuration)' --version='$(Version)' --install-prefix='$(InstallPrefix)'" Importance="High" />
<Exec Command="$(MSBuildProjectDirectory)\build.sh --install-from-source=$(InstallFromSource) --configuration='$(Configuration)' --version='$(Version)' --install-prefix='$(InstallPrefix)'" />
<Message Text="$(MSBuildProjectDirectory)\build.sh --install-from-source=$(InstallFromSource) --configuration='$(Configuration)' --version='$(Version)' --runtime='$(RuntimeIdentifier)' --install-prefix='$(InstallPrefix)'" Importance="High" />
<Exec Command="$(MSBuildProjectDirectory)\build.sh --install-from-source=$(InstallFromSource) --configuration='$(Configuration)' --version='$(Version)' --runtime='$(RuntimeIdentifier)' --install-prefix='$(InstallPrefix)'" />
</Target>

<Target Name="CoreClean">
Expand Down
30 changes: 28 additions & 2 deletions src/linux/Packaging.Linux/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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"
Expand All @@ -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."
9 changes: 8 additions & 1 deletion src/linux/Packaging.Linux/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ case "$i" in
CONFIGURATION="${i#*=}"
shift # past argument=value
;;
--runtime=*)
RUNTIME="${i#*=}"
shift # past argument=value
;;
*)
# unknown option
;;
Expand All @@ -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}"
Expand Down
33 changes: 25 additions & 8 deletions src/linux/Packaging.Linux/pack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OSPlatform)'=='windows'">net472;net8.0</TargetFrameworks>
<RuntimeIdentifiers>win-x86;osx-x64;linux-x64;osx-arm64</RuntimeIdentifiers>
<RuntimeIdentifiers>win-x86;osx-x64;linux-x64;osx-arm64;linux-arm64;linux-arm</RuntimeIdentifiers>
<PlatformTarget Condition="'$(OSPlatform)'=='windows'">x86</PlatformTarget>
<AssemblyName>git-credential-manager</AssemblyName>
<RootNamespace>GitCredentialManager</RootNamespace>
Expand Down

0 comments on commit 31ce754

Please sign in to comment.