Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: linux musl detection #502

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
46 changes: 45 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,52 @@ jobs:
name: nupkgs
path: ./dist/*.*

build-dotnet-containers:
runs-on: ubuntu-latest
name: ${{ matrix.arch }}-${{ matrix.distro }}-build-dotnet-container
strategy:
fail-fast: false
matrix:
arch:
- amd64
# - arm64
distro:
- "mcr.microsoft.com/dotnet/sdk:8.0"
- "mcr.microsoft.com/dotnet/sdk:8.0-alpine3.20"
- "mcr.microsoft.com/dotnet/sdk:8.0-alpine3.19"

steps:
- uses: actions/checkout@v4

- name: Docker dependencies
id: docker_commands
shell: bash
run: |
if [[ ${{ matrix.distro }} == *"alpine"* ]]; then
echo "deps=apk add --no-cache curl bash gzip && " >> "$GITHUB_OUTPUT"
else
echo "deps=" >> "$GITHUB_OUTPUT"
fi

- name: Restore, Build & Test
run: |
docker run \
--rm \
-v $(pwd):/${{ github.workspace }} \
-w ${{ github.workspace }} \
--platform linux/${{ matrix.arch }} \
--entrypoint /bin/sh \
${{ matrix.distro }} \
-c '${{ steps.docker_commands.outputs.deps }} \
build/download-native-libs.sh && \
dotnet restore && dotnet build --no-restore && \
dotnet test --no-build --verbosity normal'

release:
needs: build-dotnet
needs: [
build-dotnet,
build-dotnet-containers
]
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ Due to using a shared native library instead of C# for the main Pact logic only
| Linux (libc) | ARM | ❌ No |
| Linux (libc) | x86 | ❌ No |
| Linux (libc) | x64 | ✔️ Yes |
| Linux (musl) | Any | ❌ [No](https://github.com/pact-foundation/pact-net/issues/374) |
| Linux (musl) | Any | ✔️ Yes |
| OSX | x64 | ✔️ Yes |
| OSX | ARM (M1/M2) | ✔️ Yes |

Expand Down
20 changes: 19 additions & 1 deletion build/download-native-libs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,23 @@ download_native() {
if [[ "$OSTYPE" == "darwin"* ]]; then
shasum -a 256 --check --quiet "$src_sha"
else
sha256sum --check --quiet "$src_sha"
if [[ "$OSTYPE" == "linux"* ]]; then
if ldd /bin/ls >/dev/null 2>&1; then
ldd_output=$(ldd /bin/ls)
case "$ldd_output" in
*musl*)
sha256sum -c -s "$src_sha"
;;
*)
sha256sum --check --quiet "$src_sha"
;;
esac
else
sha256sum --check --quiet "$src_sha"
fi
else
sha256sum --check --quiet "$src_sha"
fi
fi

echo -e "${GREEN}OK${CLEAR}"
Expand All @@ -66,5 +82,7 @@ download_native "pact_ffi" "windows" "x86_64" "dll"
download_native "libpact_ffi" "linux" "x86_64" "so"
download_native "libpact_ffi" "macos" "x86_64" "dylib"
download_native "libpact_ffi" "macos" "aarch64" "dylib"
download_native "libpact_ffi" "linux" "x86_64-musl" "so"
download_native "libpact_ffi" "linux" "aarch64-musl" "so"

echo "Successfully downloaded FFI libraries"
121 changes: 78 additions & 43 deletions src/PactNet/PactNet.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="build_libs">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
Expand All @@ -9,49 +9,84 @@
</PropertyGroup>

<Import Project="../NuGet.targets" />
<Target Name="build_libs">
<!-- musl detection notes -->
<!-- Main fallback behaviour is to default to glibc flavour, ensuring miminal impact on existing supported targets -->
<!-- ContinueOnError True and Fallback to IsLinuxX64 / IsLinuxArm64 -->
<!-- 1. Check host is Linux - IsLinux -->
<!-- 2. Check if supported arch specific musl lib exists - IsLinuxMuslX64LibFound/IsLinuxMuslArm64LibFound -->
<!-- 3. Check if musl is the loaded libc -->
<!-- 3a. glibc hosts could have musl cross libs installed, in the standard musl location -->
<!-- 3b. use ldd on a well known binary such as /bin/sh and grep for musl -->
<!-- 3c. note ldd may not be available on all musl targets -->
<PropertyGroup>
<IsLinux>False</IsLinux>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'True'">True</IsLinux>
<IsLinuxMuslX64LibFound Condition="$([System.IO.File]::Exists('/lib/ld-musl-x86_64.so.1')) == 'True'">True</IsLinuxMuslX64LibFound>
<IsLinuxMuslArm64LibFound Condition="$([System.IO.File]::Exists('/lib/ld-musl-aarch64.so.1')) == 'True'">True</IsLinuxMuslArm64LibFound>
</PropertyGroup>
<!-- only run this check if linux and the musl shared libs were found -->
<Exec Command="ldd /bin/sh | grep musl" ConsoleToMSBuild="true" StandardOutputImportance="low" ContinueOnError="true" Condition="$(IsLinux) == 'True' And ($(IsLinuxMuslX64LibFound) == 'True' Or $(IsLinuxMuslArm64LibFound) == 'True')">
<Output TaskParameter="ExitCode" PropertyName="IsLinuxMuslLoaded"/>
</Exec>
<PropertyGroup>
<IsWindows>False</IsWindows>
<IsOSX>False</IsOSX>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'True'">True</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'True'">True</IsOSX>
<IsArm64>False</IsArm64>
<IsArm64 Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'Arm64'">True</IsArm64>
<IsLinuxX64 Condition="'$(IsLinux)' == 'True' And '$(IsArm64)' == 'False'">True</IsLinuxX64>
<IsLinuxArm64 Condition="'$(IsLinux)' == 'True' And '$(IsArm64)' == 'True'">True</IsLinuxArm64>
<IsLinuxMuslX64 Condition="'$(IsLinux)' == 'True' And '$(IsLinuxMuslLoaded)' == '0' And '$(IsArm64)' == 'False'">True</IsLinuxMuslX64>
<IsLinuxMuslArm64 Condition="'$(IsLinux)' == 'True' And '$(IsLinuxMuslLoaded)' == '0' And '$(IsArm64)' == 'True'">True</IsLinuxMuslArm64>
</PropertyGroup>

<PropertyGroup>
<IsWindows>False</IsWindows>
<IsLinux>False</IsLinux>
<IsOSX>False</IsOSX>
<IsArm64>False</IsArm64>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'True'">True</IsWindows>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'True'">True</IsLinux>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'True'">True</IsOSX>
<IsArm64 Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'Arm64'">True</IsArm64>
</PropertyGroup>

<ItemGroup>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\windows\x86_64\pact_ffi.dll">
<Link>pact_ffi.dll</Link>
<PackagePath>runtimes/win-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsWindows)'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\linux\x86_64\libpact_ffi.so">
<Link>libpact_ffi.so</Link>
<PackagePath>runtimes/linux-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsLinux)'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\macos\x86_64\libpact_ffi.dylib">
<Link>libpact_ffi.dylib</Link>
<PackagePath>runtimes/osx-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsOSX)' == 'True' And '$(IsArm64)' == 'False'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\macos\aarch64\libpact_ffi.dylib">
<Link>libpact_ffi.dylib</Link>
<PackagePath>runtimes/osx-arm64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsOSX)' == 'True' And '$(IsArm64)' == 'True'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>

<ItemGroup>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\windows\x86_64\pact_ffi.dll">
<Link>pact_ffi.dll</Link>
<PackagePath>runtimes/win-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsWindows)'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\linux\x86_64\libpact_ffi.so">
<Link>libpact_ffi.so</Link>
<PackagePath>runtimes/linux-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsLinuxX64)' == 'True'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\linux\x86_64-musl\libpact_ffi.so">
<Link>libpact_ffi.so</Link>
<PackagePath>runtimes/linux-x64-musl/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsLinuxMuslX64)' == 'True'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\linux\aarch64-musl\libpact_ffi.so">
<Link>libpact_ffi.so</Link>
<PackagePath>runtimes/linux-arm64-musl/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsLinuxMuslArm64)' == 'True'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\macos\x86_64\libpact_ffi.dylib">
<Link>libpact_ffi.dylib</Link>
<PackagePath>runtimes/osx-x64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsOSX)' == 'True' And '$(IsArm64)' == 'False'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\macos\aarch64\libpact_ffi.dylib">
<Link>libpact_ffi.dylib</Link>
<PackagePath>runtimes/osx-arm64/native</PackagePath>
<Pack>true</Pack>
<CopyToOutputDirectory Condition="'$(IsOSX)' == 'True' And '$(IsArm64)' == 'True'">PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
</Target>
<ItemGroup>
<Content Include="$(MSBuildProjectDirectory)\..\..\build\PactNet.targets">
<PackagePath>build/net462/</PackagePath>
Expand Down