diff --git a/.github/workflows/build-and-publish-natives.yml b/.github/workflows/build-and-publish-natives.yml
new file mode 100644
index 000000000..fd4287e9d
--- /dev/null
+++ b/.github/workflows/build-and-publish-natives.yml
@@ -0,0 +1,40 @@
+name: Build & Publish NetCord.Natives
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - 'Natives/**'
+ - '.github/workflows/build-natives.yml'
+ - '.github/workflows/build-and-publish-natives.yml'
+ tags:
+ - "[0-9]+.[0-9]+.[0-9]+"
+ - "[0-9]+.[0-9]+.[0-9]+-*"
+
+jobs:
+ build-natives:
+ uses: ./.github/workflows/build-natives.yml
+
+ publish:
+ needs: [build-natives]
+ runs-on: ubuntu-latest
+ permissions:
+ packages: write
+
+ steps:
+ - name: Download All NuGet Package Artifacts
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ path: artifacts/pkgs
+ pattern: NetCord.Natives.*.packages
+ merge-multiple: true
+
+ - name: Publish packages
+ env:
+ KEY: ${{ secrets.NUGET_API_KEY }}
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ dotnet nuget push artifacts/pkgs/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push artifacts/pkgs/*.snupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push artifacts/pkgs/*.nupkg -k $GH_TOKEN -s https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --skip-duplicate
+ dotnet nuget push artifacts/pkgs/*.snupkg -k $GH_TOKEN -s https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --skip-duplicate
diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml
index e0e2b4c86..2cc2198ff 100644
--- a/.github/workflows/build-and-publish.yml
+++ b/.github/workflows/build-and-publish.yml
@@ -7,7 +7,11 @@ on:
- "[0-9]+.[0-9]+.[0-9]+-*"
jobs:
- build-and-publish:
+ build:
+ uses: ./.github/workflows/build.yml
+
+ publish:
+ needs: build
runs-on: ubuntu-latest
permissions:
contents: write
@@ -15,9 +19,18 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+
+ - name: Download NuGet Package Artifacts
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: NuGet Packages
+ path: artifacts/pkgs
+
+ - name: Download Documentation Artifacts
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
- fetch-depth: 0
- filter: tree:0
+ name: Documentation Artifacts
+ path: artifacts/docs
- name: Install Nix
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
@@ -26,50 +39,13 @@ jobs:
shell: &dev-shell 'nix develop -c bash -eo pipefail {0}'
run: 'true'
- - name: Restore dependencies
- shell: *dev-shell
- run: dotnet restore
-
- - name: Build
- shell: *dev-shell
- run: dotnet build -c Release --no-restore --warnaserror
-
- - name: Test
- shell: *dev-shell
- run: dotnet test -c Release --no-build --verbosity normal
-
- - name: Pack Packages
- shell: *dev-shell
- run: |
- dotnet pack NetCord -c Release --no-build
- dotnet pack NetCord.Services -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting.Services -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting.AspNetCore -c Release --no-build
-
- - name: Setup docs environment
- shell: &docs-shell 'nix develop .#docs -c bash -eo pipefail {0}'
- run: 'true'
-
- - name: Build Documentation
- shell: *docs-shell
- working-directory: Documentation
- run: |
- npm install
- npm run lint
- npm run test
- npm run build
-
- name: Publish Packages
shell: *dev-shell
env:
KEY: ${{ secrets.NUGET_API_KEY }}
run: |
- dotnet nuget push NetCord/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
- dotnet nuget push NetCord.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
- dotnet nuget push Hosting/NetCord.Hosting/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
- dotnet nuget push Hosting/NetCord.Hosting.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
- dotnet nuget push Hosting/NetCord.Hosting.AspNetCore/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push artifacts/pkgs/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push artifacts/pkgs/*.snupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate
- name: Deploy Documentation
uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0
@@ -79,7 +55,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
key: ${{ secrets.SSH_KEY }}
rm: true
- source: Documentation/_site
+ source: artifacts/docs
strip_components: 2
target: ~/NetCord/html
@@ -89,7 +65,7 @@ jobs:
TAG: ${{ github.ref_name }}
IS_PRERELEASE: ${{ contains(github.ref_name, '-') }}
run: |
- cp -r Documentation/_site "Documentation-$TAG"
+ cp -r artifacts/docs "Documentation-$TAG"
zip -r "Documentation-$TAG.zip" "Documentation-$TAG"
tar -czvf "Documentation-$TAG.tar.gz" "Documentation-$TAG"
@@ -97,11 +73,7 @@ jobs:
rm -r "Documentation-$TAG"
FILES=(
- NetCord/bin/Release/*.*nupkg
- NetCord.Services/bin/Release/*.*nupkg
- Hosting/NetCord.Hosting/bin/Release/*.*nupkg
- Hosting/NetCord.Hosting.Services/bin/Release/*.*nupkg
- Hosting/NetCord.Hosting.AspNetCore/bin/Release/*.*nupkg
+ artifacts/pkgs/*.nupkg
"Documentation-$TAG.zip"
"Documentation-$TAG.tar.gz"
)
@@ -116,20 +88,3 @@ jobs:
--prerelease="$IS_PRERELEASE" \
"${FILES[@]}"
fi
-
- - name: Upload Build Artifacts
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
- with:
- name: Build Artifacts
- path: |
- NetCord/bin/Release
- NetCord.Services/bin/Release
- Hosting/NetCord.Hosting/bin/Release
- Hosting/NetCord.Hosting.Services/bin/Release
- Hosting/NetCord.Hosting.AspNetCore/bin/Release
-
- - name: Upload Documentation Artifacts
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
- with:
- name: Documentation Artifacts
- path: Documentation/_site
diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml
new file mode 100644
index 000000000..31c953dba
--- /dev/null
+++ b/.github/workflows/build-natives.yml
@@ -0,0 +1,425 @@
+name: Build NetCord.Natives
+
+on:
+ workflow_call:
+ workflow_dispatch:
+ inputs:
+ GenerateBinLog:
+ type: boolean
+ default: false
+ MSBuildVerbosity:
+ type: choice
+ description: 'MSBuild Verbosity Level'
+ required: true
+ default: 'Minimal'
+ options:
+ - Quiet
+ - Minimal
+ - Normal
+ - Detailed
+ - Diagnostic
+ push:
+ paths:
+ - 'Natives/**'
+ - '.github/workflows/build-natives.yml'
+
+jobs:
+ build-natives:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - rid: win-x64
+ runs-on: windows-latest
+ vcpkg-os-target: windows
+ vcpkg-platform-target: x64
+ use-nix: false
+ musl: false
+ shell_command: pwsh
+ - rid: win-arm64
+ runs-on: windows-11-arm
+ vcpkg-os-target: windows
+ vcpkg-platform-target: arm64
+ use-nix: false
+ musl: false
+ shell_command: pwsh
+ - rid: osx-x64
+ runs-on: macos-15-intel
+ vcpkg-os-target: osx
+ vcpkg-platform-target: x64
+ use-nix: true
+ musl: false
+ shell_command: nix develop .#natives -c bash -eo pipefail {0}
+ - rid: osx-arm64
+ runs-on: macos-15
+ vcpkg-os-target: osx
+ vcpkg-platform-target: arm64
+ use-nix: true
+ musl: false
+ shell_command: nix develop .#natives -c bash -eo pipefail {0}
+ - rid: linux-x64
+ runs-on: ubuntu-latest
+ vcpkg-os-target: linux
+ vcpkg-platform-target: x64
+ use-nix: true
+ musl: false
+ shell_command: nix develop .#natives -c bash -eo pipefail {0}
+ - rid: linux-arm64
+ runs-on: ubuntu-24.04-arm
+ vcpkg-os-target: linux
+ vcpkg-platform-target: arm64
+ use-nix: true
+ musl: false
+ shell_command: nix develop .#natives -c bash -eo pipefail {0}
+ - rid: linux-musl-x64
+ runs-on: ubuntu-latest
+ vcpkg-os-target: linux-musl
+ vcpkg-platform-target: x64
+ use-nix: true
+ musl: true
+ shell_command: nix develop .#natives-musl -c bash -eo pipefail {0}
+ - rid: linux-musl-arm64
+ runs-on: ubuntu-24.04-arm
+ vcpkg-os-target: linux-musl
+ vcpkg-platform-target: arm64
+ use-nix: true
+ musl: true
+ shell_command: nix develop .#natives-musl --option max-jobs 1 --option cores 3 -c bash -eo pipefail {0}
+
+ runs-on: ${{ matrix.runs-on }}
+ permissions:
+ contents: read
+ packages: write
+ defaults:
+ run:
+ shell: ${{ matrix.shell_command }}
+ env:
+ VCPKG_ROOT: ${{ github.workspace }}/Natives/NetCord.Natives/vcpkg
+ VcpkgOSTarget: ${{ matrix.vcpkg-os-target }}
+ VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }}
+ GITHUB_PACKAGES_FEED: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
+ VCPKG_BINARY_SOURCES: "clear;nugetconfig,${{ github.workspace }}/Natives/NetCord.Natives/vcpkg-nuget.config,readwrite"
+ Configuration: Release
+ DotnetVerbose: ${{ github.event.inputs.MSBuildVerbosity || inputs.MSBuildVerbosity || 'Minimal' }}
+ GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ fetch-depth: 0
+ filter: tree:0
+ submodules: true
+
+ - name: Install Nix
+ if: ${{ matrix.use-nix }}
+ uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
+
+ - name: Magic Nix Cache
+ if: ${{ matrix.use-nix && matrix.musl }}
+ uses: DeterminateSystems/magic-nix-cache-action@908b263ff629f4cc17666315b7fd3ec127c6244d # v14
+
+ - name: Setup dev environment (Nix)
+ if: ${{ matrix.use-nix }}
+ run: 'true'
+
+ - name: Setup vcpkg (Windows)
+ if: ${{ !matrix.use-nix }}
+ run: |
+ & "${{ env.VCPKG_ROOT }}\bootstrap-vcpkg.bat" -disableMetrics
+
+ # Fetch the nuget path, filter out any warning lines, and run it
+ $nugetPath = & "${{ env.VCPKG_ROOT }}\vcpkg" fetch nuget | Select-Object -Last 1
+
+ Write-Host "NuGet path: $nugetPath"
+
+ & $nugetPath sources add `
+ -Source "${{ env.GITHUB_PACKAGES_FEED }}" `
+ -Name "GithubPackages" `
+ -UserName "${{ github.repository_owner }}" `
+ -Password "${{ secrets.VCPKG_NUGET_TOKEN }}" `
+ -StorePasswordInClearText `
+ -ConfigFile "${{ github.workspace }}\Natives\NetCord.Natives\vcpkg-nuget.config"
+
+ # Set the api key for the GitHub Packages feed
+ & $nugetPath setapikey "${{ secrets.VCPKG_NUGET_TOKEN }}" `
+ -Source "${{ env.GITHUB_PACKAGES_FEED }}" `
+ -ConfigFile "${{ github.workspace }}\Natives\NetCord.Natives\vcpkg-nuget.config"
+
+ # Tell NuGet to use this feed by default for push operations
+ & $nugetPath config `
+ -ConfigFile "${{ github.workspace }}\Natives\NetCord.Natives\vcpkg-nuget.config" `
+ -Set defaultPushSource="${{ env.GITHUB_PACKAGES_FEED }}"
+
+ - name: Setup vcpkg (Nix)
+ if: ${{ matrix.use-nix }}
+ run: |
+ # Capture the nuget.exe path to a local variable
+ export NUGET_PATH=$("${{ env.VCPKG_ROOT }}/vcpkg" fetch nuget | tail -n 1)
+
+ echo "NuGet path: $NUGET_PATH"
+
+ mono "$NUGET_PATH" sources add \
+ -Source "${{ env.GITHUB_PACKAGES_FEED }}" \
+ -Name "GithubPackages" \
+ -UserName "${{ github.repository_owner }}" \
+ -Password "${{ secrets.VCPKG_NUGET_TOKEN }}" \
+ -StorePasswordInClearText \
+ -ConfigFile "${{ github.workspace }}/Natives/NetCord.Natives/vcpkg-nuget.config"
+
+ # Set the api key for the GitHub Packages feed
+ mono "$NUGET_PATH" setapikey "${{ secrets.VCPKG_NUGET_TOKEN }}" \
+ -Source "${{ env.GITHUB_PACKAGES_FEED }}" \
+ -ConfigFile "${{ github.workspace }}/Natives/NetCord.Natives/vcpkg-nuget.config"
+
+ # Tell NuGet to use this feed by default for push operations
+ mono "$NUGET_PATH" config \
+ -ConfigFile "${{ github.workspace }}/Natives/NetCord.Natives/vcpkg-nuget.config" \
+ -Set defaultPushSource="${{ env.GITHUB_PACKAGES_FEED }}"
+
+ - name: Setup .NET Core SDK (Windows)
+ if: ${{ !matrix.use-nix }}
+ uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ with:
+ global-json-file: global.json
+
+ - name: Restore
+ run: >
+ dotnet restore Natives/NetCord.Natives.slnx
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }}
+
+ - name: Build natives projects for ${{ matrix.rid }}
+ id: build_step
+ run: >
+ dotnet build Natives/NetCord.Natives.slnx --no-restore
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && format('-bl:build.binlog -p:NativeAotBinLogPath={0}/nativeaotapptest.binlog', github.workspace) || '' }}
+ -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ matrix.rid }}"
+ -p:GeneratePackageOnBuild=false
+
+ - name: Test natives outputs for ${{ matrix.rid }}
+ run: >
+ ${{ matrix.musl && 'docker run --rm -v $PWD:$PWD -w $PWD -e DotnetVerbose -e Configuration -e MINVERVERSIONOVERRIDE=1.0.0 -e VCPKG_ROOT -e VCPKG_FORCE_SYSTEM_BINARIES=1 -e VcpkgOSTarget -e VcpkgPlatformTarget mcr.microsoft.com/dotnet/sdk:10.0-alpine3.23-aot sh -c "apk add build-base cmake ninja zip unzip curl git perl linux-headers && ./Natives/NetCord.Natives/vcpkg/bootstrap-vcpkg.sh && ' || '' }}
+ dotnet test Natives/NetCord.Natives.slnx
+ --no-restore
+ --no-build
+ --filter 'FullyQualifiedName!~NativeAotStaticLinking_WithPackageVer'
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }}
+ --logger 'console;verbosity=detailed'
+ --logger GitHubActions
+ ${{ matrix.musl && '"' || '' }}
+
+ - name: Upload Binary Logs
+ if: ${{ env.GenerateBinLog == 'true' && always() }}
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: ${{ matrix.rid }}-build-natives-binlogs
+ path: |
+ *.binlog
+
+ - name: Clean Symbollic Links (Nix)
+ if: ${{ matrix.use-nix }}
+ run: |
+ find Natives/NetCord.Natives/bin/${{ matrix.rid }}/natives/${{ env.VcpkgPlatformTarget }}-${{ env.VcpkgOSTarget }}-dynamic/lib/ -type l -exec rm {} \;
+ find Natives/NetCord.Natives/bin/${{ matrix.rid }}/natives-static/${{ env.VcpkgPlatformTarget }}-${{ env.VcpkgOSTarget }}/lib/ -type l -exec rm {} \;
+
+ - name: Upload Natives Artifact
+ if: ${{ always() && steps.build_step.outcome == 'success' }}
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: NetCord.Natives.${{ matrix.rid }}.build
+ path: |
+ Natives/NetCord.Natives/bin/${{ matrix.rid }}
+
+ pack-natives:
+ needs: [build-natives]
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ defaults:
+ run:
+ shell: nix develop -c bash -eo pipefail {0}
+ env:
+ Configuration: Release
+ DotnetVerbose: ${{ github.event.inputs.MSBuildVerbosity || inputs.MSBuildVerbosity || 'Minimal' }}
+ GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ fetch-depth: 0
+ filter: tree:0
+
+ - name: Download All Natives Artifact
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ path: artifacts/natives-build
+ pattern: NetCord.Natives.*.packages
+ merge-multiple: true
+
+ - name: Install Nix
+ uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
+
+ - name: Setup dev environment
+ run: 'true'
+
+ - name: Restore
+ run: >
+ dotnet restore Natives/NetCord.Natives/NetCord.Natives.csproj
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }}
+
+ - name: Pack Natives NuGet Package
+ id: pack_step
+ run: >
+ dotnet pack Natives/NetCord.Natives/NetCord.Natives.csproj
+ --no-build
+ --no-restore
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }}
+ -p:VcpkgArtifactsRoot=${{ github.workspace }}/artifacts/natives-build/
+ -o ${{ github.workspace }}/
+
+ - name: Upload Binary Logs
+ if: ${{ env.GenerateBinLog == 'true' && always() }}
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: pack-natives-binlogs
+ path: |
+ *.binlog
+
+ - name: Upload NuGet Package Artifact
+ if: ${{ always() && steps.pack_step.outcome == 'success' }}
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: NetCord.Natives.packages
+ path: |
+ *.nupkg
+ *.snupkg
+
+ test-package:
+ needs: [pack-natives]
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - rid: win-x64
+ runs-on: windows-latest
+ use-nix: false
+ musl: false
+ shell_command: pwsh
+ - rid: win-arm64
+ runs-on: windows-11-arm
+ use-nix: false
+ musl: false
+ shell_command: pwsh
+ - rid: osx-x64
+ runs-on: macos-15-intel
+ use-nix: true
+ musl: false
+ shell_command: nix develop -c bash -eo pipefail {0}
+ - rid: osx-arm64
+ runs-on: macos-15
+ use-nix: true
+ musl: false
+ shell_command: nix develop -c bash -eo pipefail {0}
+ - rid: linux-x64
+ runs-on: ubuntu-latest
+ use-nix: true
+ musl: false
+ shell_command: nix develop -c bash -eo pipefail {0}
+ - rid: linux-arm64
+ runs-on: ubuntu-24.04-arm
+ use-nix: true
+ musl: false
+ shell_command: nix develop -c bash -eo pipefail {0}
+ - rid: linux-musl-x64
+ runs-on: ubuntu-latest
+ use-nix: true
+ musl: true
+ shell_command: nix develop -c bash -eo pipefail {0}
+ - rid: linux-musl-arm64
+ runs-on: ubuntu-24.04-arm
+ use-nix: true
+ musl: true
+ shell_command: nix develop -c bash -eo pipefail {0}
+
+ runs-on: ${{ matrix.runs-on }}
+ permissions:
+ contents: read
+ defaults:
+ run:
+ shell: ${{ matrix.shell_command }}
+ env:
+ Configuration: Release
+ DotnetVerbose: ${{ github.event.inputs.MSBuildVerbosity || inputs.MSBuildVerbosity || 'Minimal' }}
+ GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }}
+ RestoreSources: ${{ github.workspace }}/artifacts/pkgs
+ NoNativesBuild: true
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ fetch-depth: 0
+ filter: tree:0
+ submodules: true
+
+ - name: Download Natives Packages Artifact
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: NetCord.Natives.packages
+ path: artifacts/pkgs
+
+ - name: Install Nix
+ if: ${{ matrix.use-nix }}
+ uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
+
+ - name: Setup dev environment (Nix)
+ if: ${{ matrix.use-nix }}
+ run: 'true'
+
+ - name: Setup .NET Core SDK (Windows)
+ if: ${{ !matrix.use-nix }}
+ uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ with:
+ global-json-file: global.json
+
+ - name: Restore
+ run: >
+ dotnet restore Natives/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }}
+
+ - name: Build tests for ${{ matrix.rid }}
+ run: >
+ dotnet build Natives/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && format('-bl:build.binlog -p:NativeAotBinLogPath={0}/nativeaotapptest.binlog', github.workspace) || '' }}
+ -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ matrix.rid }}"
+ -p:GeneratePackageOnBuild=false
+
+ - name: Test packages for ${{ matrix.rid }}
+ run: >
+ ${{ matrix.musl && 'docker run --rm -v $PWD:$PWD -w $PWD -e DotnetVerbose -e RestoreSources -e Configuration -e MINVERVERSIONOVERRIDE=1.0.0 -e VCPKG_ROOT -e VCPKG_FORCE_SYSTEM_BINARIES=1 mcr.microsoft.com/dotnet/sdk:10.0-alpine3.23-aot sh -c "apk add build-base cmake ninja zip unzip curl git && ./Natives/NetCord.Natives/vcpkg/bootstrap-vcpkg.sh && ' || '' }}
+ dotnet test Natives/NetCord.Natives.slnx
+ --no-restore
+ --no-build
+ --filter 'FullyQualifiedName~NativeAotStaticLinking_WithPackageVer'
+ -v ${{ env.DotnetVerbose }}
+ ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }}
+ --logger 'console;verbosity=detailed'
+ --logger GitHubActions
+ ${{ matrix.musl && '"' || '' }}
+
+ - name: Upload Binary Logs
+ if: ${{ env.GenerateBinLog == 'true' && always() }}
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: ${{ matrix.rid }}-test-package-binlogs
+ path: |
+ *.binlog
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 20ac2600e..85845fa45 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,6 +1,7 @@
name: Build
on:
+ workflow_call:
pull_request:
branches:
- main
@@ -31,24 +32,26 @@ jobs:
- name: Restore dependencies
shell: *dev-shell
- run: dotnet restore
+ run: |
+ dotnet restore NetCord.slnx
- name: Build
shell: *dev-shell
- run: dotnet build -c Release --no-restore --warnaserror
+ run: |
+ dotnet build NetCord.slnx -c Release --no-restore --warnaserror
- name: Test
shell: *dev-shell
- run: dotnet test -c Release --no-build --verbosity normal
+ run: dotnet test NetCord.slnx -c Release --no-build --verbosity normal
- name: Pack Packages
shell: *dev-shell
run: |
- dotnet pack NetCord -c Release --no-build
- dotnet pack NetCord.Services -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting.Services -c Release --no-build
- dotnet pack Hosting/NetCord.Hosting.AspNetCore -c Release --no-build
+ dotnet pack NetCord -c Release --no-build -o pkgs/
+ dotnet pack NetCord.Services -c Release --no-build -o pkgs/
+ dotnet pack Hosting/NetCord.Hosting -c Release --no-build -o pkgs/
+ dotnet pack Hosting/NetCord.Hosting.Services -c Release --no-build -o pkgs/
+ dotnet pack Hosting/NetCord.Hosting.AspNetCore -c Release --no-build -o pkgs/
- name: Setup docs environment
shell: &docs-shell 'nix develop .#docs -c bash -eo pipefail {0}'
@@ -63,6 +66,20 @@ jobs:
npm run test
npm run build
+ - name: Upload NuGet Package Artifacts
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: NuGet Packages
+ path: |
+ pkgs/*.nupkg
+ pkgs/*.snupkg
+
+ - name: Upload Documentation Artifacts
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: Documentation Artifacts
+ path: Documentation/_site
+
- name: Upload Build Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
@@ -73,9 +90,3 @@ jobs:
Hosting/NetCord.Hosting/bin/Release
Hosting/NetCord.Hosting.Services/bin/Release
Hosting/NetCord.Hosting.AspNetCore/bin/Release
-
- - name: Upload Documentation Artifacts
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
- with:
- name: Documentation Artifacts
- path: Documentation/_site
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..4f87b73d4
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "Natives/NetCord.Natives/vcpkg"]
+ path = Natives/NetCord.Natives/vcpkg
+ url = https://github.com/microsoft/vcpkg.git
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 13f70daeb..b8e5ad4f4 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -23,6 +23,9 @@
+
+
+
diff --git a/Documentation/guides/installing-native-dependencies.md b/Documentation/guides/installing-native-dependencies.md
index 26461d5ad..7ef452b44 100644
--- a/Documentation/guides/installing-native-dependencies.md
+++ b/Documentation/guides/installing-native-dependencies.md
@@ -1,91 +1,139 @@
# Installing Native Dependencies
-This is a hidden guide that is not visible in the guides index! If you are reading this, you are probably looking for information on how to install native dependencies for HTTP interactions or voice.
+NetCord relies on several native libraries for high-performance audio processing and encryption. NetCord provides prebuilt native binaries via NuGet packages, which is the recommended way to manage these dependencies.
-## HTTP Interactions
+## Native Dependencies
-For HTTP interactions, [Libsodium](https://doc.libsodium.org/installation) is required.
+- **Libsodium**: Used for encryption and provides fallback encryption modes. NetCord attempts to use the platform's native AES-GCM encryption for voice connections. However, Libsodium becomes essential in two scenarios:
+ 1. The native AES-GCM is unavailable on the system.
+ 2. The target Discord voice server does not support AES-GCM encryption.
+- **Opus**: The standard audio codec used by Discord for voice chat.
+- **Zstandard (Zstd)**: Required for compressing WebSocket payloads when enabled.
-## Voice
+## NuGet Packages (Recommended)
-For voice:
-- [Libdave](https://github.com/discord/libdave) is required.
-- [Libsodium](https://doc.libsodium.org/installation) **is not generally** required, but it **is highly recommended for production bots**. It is caused by the fact that generally @NetCord.Gateway.Voice.Encryption.Aes256GcmRtpSizeEncryption, which does not require Libsodium, is supported by Discord and is used by default. However, there is a small chance that Discord will not support this encryption mode for your connection. In this case, @NetCord.Gateway.Voice.Encryption.XChaCha20Poly1305RtpSizeEncryption, which does require Libsodium, is used by default.
-- [Opus](https://opus-codec.org/downloads) is only required when you are using `Opus` prefixed classes.
+NetCord distributes these dependencies as individually packaged NuGet references — one package per native library. You can reference only the libraries your project actually uses, or use the meta-package to pull them all in for convenience.
-## Installation
+| Package | Native library | NuGet |
+|-----------------------------|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `NetCord.Natives` | **Meta-package** (references all below) | [](https://www.nuget.org/packages/NetCord.Natives) |
+| `NetCord.Natives.Dave` | libdave, mlspp, hpke, openssl (libcrypto) | [](https://www.nuget.org/packages/NetCord.Natives.Dave) |
+| `NetCord.Natives.Sodium` | libsodium | [](https://www.nuget.org/packages/NetCord.Natives.Sodium) |
+| `NetCord.Natives.Opus` | opus | [](https://www.nuget.org/packages/NetCord.Natives.Opus) |
+| `NetCord.Natives.Zstandard` | zstd | [](https://www.nuget.org/packages/NetCord.Natives.Zstandard) |
-### [Dynamic Linking](#tab/dynamic)
+### Supported Platforms
-For dynamic linking, you can install Libsodium for the most popular platforms by referencing the [official Libsodium NuGet package](https://www.nuget.org/packages/libsodium).
+Each package ships runtime binaries (`.dll` / `.so` / `.dylib`) for all supported platforms and static libraries for NativeAOT:
-### Manual or System-wide Installation
+| Platform | RID | NativeAOT Support |
+|------------------|--------------------|--------------------|
+| Windows x64 | `win-x64` | ✓ (Static CRT /MT) |
+| Windows ARM64 | `win-arm64` | ✓ (Static CRT /MT) |
+| Linux x64 | `linux-x64` | ✓ (Dynamic CRT) |
+| Linux ARM64 | `linux-arm64` | ✓ (Dynamic CRT) |
+| Linux musl x64 | `linux-musl-x64` | ✓ (Dynamic CRT) |
+| Linux musl ARM64 | `linux-musl-arm64` | ✓ (Dynamic CRT) |
+| ⓘ macOS x64 | `osx-x64` | ✓ (Dynamic CRT) |
+| ⓘ macOS ARM64 | `osx-arm64` | ✓ (Dynamic CRT) |
-#### Windows
+> ⓘ macOS packages are built and published, but function verification tests are skipped due to limitations with `dyld`. They are expected to work correctly, but we recommend testing on macOS before production use.
-For dynamic linking on Windows, you need to use the dynamic link libraries (`libdave`, `libsodium`, and/or `opus`). Here's how to set it up:
-- Download or build the dynamic link libraries (`libdave`, `libsodium`, and/or `opus`) compatible with your development environment.
+## Dynamic Linking
-- Place these files in the runtime directory of your application. This is the folder where your application's executable is located.
+For standard .NET applications, reference the packages for the native libraries you need. The correct runtime binaries are automatically copied and loaded.
-#### Linux and MacOS
+You can add these packages using the .NET CLI or directly to your `.csproj` file:
-Dynamic linking on Linux and MacOS involves using shared libraries (`libdave`, `libsodium`, and/or `opus`). You can install them using your system's package manager if available or follow these steps to install them manually:
-- Download or build the shared libraries (`libdave`, `libsodium`, and/or `opus`) that are compatible with your development environment.
+```bash
+# Add individual packages...
+dotnet add package NetCord.Natives.Dave
-- Place these files in the runtime directory of your application, which is the folder where your application's executable is located.
-
-### [Static Linking](#tab/static)
-
-> [!NOTE]
-> Static linking requires [Native AOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot) compilation.
-
-#### Windows
-
-When using static linking on Windows, you need to link to the static libraries (`libdave`, `libsodium`, and/or `opus`). Here are the steps to set up static linking in your application:
-- Download or build the static libraries (`libdave`, `libsodium`, and/or `opus`) compatible with your development environment.
-- Link these libraries in your project settings. Ensure that you specify the correct paths to these libraries:
- ```xml
-
-
-
-
-
-
-
-
-
-
- ```
+# ...or just add the meta-package for all of them
+dotnet add package NetCord.Natives
+```
+```xml
+
+
+
+
+
+
+
+```
-You don't need to place any of these files in the runtime directory, as static linking embeds the library code directly into your application, eliminating the need for separate files.
+## NativeAOT (Static Linking)
-#### Linux and MacOS
+When using [NativeAOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot), static libraries are automatically linked from the NuGet package, embedding the necessary native code directly into your executable.
-Static linking on Linux and MacOS involves linking your application with the static libraries (`libdave`, `libsodium`, and/or `opus`). You can install them using your system's package manager if available or download or build the static libraries (`libdave`, `libsodium`, and/or `opus`) compatible with your development environment manually.
+You must explicitly register each native library with `` so the AOT compiler includes it:
-Link these libraries in your project settings. Make sure you specify the correct paths to these libraries:
```xml
-
-
-
-
-
+
```
-Since you're statically linking, you won't need to place any of these files in the runtime directory. The necessary code from the libraries will be included directly in your application.
+When `DirectPInvoke` is set, the corresponding dynamic libraries are automatically excluded from the publish output.
+
+### Excluding libraries manually
+
+If you are managing dependencies via NuGet and want to exclude a library, you can simply omit its ``.
+
+However, if you are building NetCord (and/or NetCord.Natives) from source (or using the meta-package) and want to provide your own binaries, use the `NetCordExcludeNatives` property. This explicitly prevents the specified libraries from being copied to your output directory **and** stops them from being statically linked during NativeAOT compilation.
+
+```xml
+
+ libdave;libsodium
+
+```
+
+## Custom Manual/System-wide Installation
-***
+If you are developing for an unsupported platform or require a custom-built native binary, you may handle native dependencies manually.
-#### Installation External Links
+1. **Obtain Binaries**: Use your system's package manager (e.g., `apt`, `brew`, `dnf`) if available, or download the binaries from the official sources listed below.
+2. **Placement**: Ensure the native libraries are available to your application at runtime. On Windows, place `.dll` files in your application's output directory. On Unix-like systems, ensure shared libraries are in your `LD_LIBRARY_PATH` or system standard paths.
-| Library | Installation Link |
+### Installation Links
+
+| Library | Link |
|-----------|---------------------------------------------|
| Libdave | https://github.com/discord/libdave/releases |
| Libsodium | https://doc.libsodium.org/installation |
| Opus | https://opus-codec.org/downloads |
+| Zstd | https://github.com/facebook/zstd/releases |
+
+## Troubleshooting
+
+- Ensure that the correct versions are installed and accessible to your application.
+- Use tools like `ldd` (Linux) or `Dependency Walker` (Windows) to verify that your application is correctly linking against the native libraries.
+
+---
+
+## Extra Notes on Native Dependencies
+
+The native packaging model is designed to make managing dependencies as transparent and reliable as possible.
+
+### What You Get
+* **Ready-to-use binaries**: We provide prebuilt runtime binaries for standard .NET and static libraries for NativeAOT.
+* **Automatic Configuration**: MSBuild files are included in the packages to automatically handle paths and linking requirements, so you don't have to manually configure build settings.
+
+### Built-in Compliance
+
+All necessary licenses and copyright notices from the original native project sources are bundled within each package under the `licenses/` directory.
+
+| Library | License | Remarks |
+|---------------|--------------|-----------------------------|
+| **Libdave** | MIT | Discord voice communication |
+| **Libsodium** | ISC | Used for encryption |
+| **OpenSSL** | Apache 2.0 | Cryptographic operations |
+| **Opus** | BSD-3-Clause | Audio codec |
+| **Zstd** | BSD-3-Clause | Compression |
+
+### Reproducible Builds
+
+Dependencies are strictly pinned using [vcpkg](https://github.com/microsoft/vcpkg) baselines, ensuring identical build results regardless of when or where the build runs.
diff --git a/Natives/NetCord.Natives.slnx b/Natives/NetCord.Natives.slnx
new file mode 100644
index 000000000..1c7166ef8
--- /dev/null
+++ b/Natives/NetCord.Natives.slnx
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Natives/NetCord.Natives/.gitignore b/Natives/NetCord.Natives/.gitignore
new file mode 100644
index 000000000..07db887c6
--- /dev/null
+++ b/Natives/NetCord.Natives/.gitignore
@@ -0,0 +1 @@
+*.tlog
diff --git a/Natives/NetCord.Natives/NetCord.Natives.csproj b/Natives/NetCord.Natives/NetCord.Natives.csproj
new file mode 100644
index 000000000..b7fa16ff8
--- /dev/null
+++ b/Natives/NetCord.Natives/NetCord.Natives.csproj
@@ -0,0 +1,385 @@
+
+
+
+ Pre-built native libraries for NetCord, $(Description)
+ false
+ false
+ false
+ true
+ $(NoWarn);NU5128
+
+ $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..\..\..'))
+
+
+
+
+
+
+ vcpkg\%(Filename)%(Extension)
+
+
+
+
+
+ <_IsPackingNative Condition="'$(_IsPackingNative)' == ''">false
+
+ debug
+
+ bin
+
+ $(VCPKG_ROOT)
+ $(MSBuildProjectDirectory)\vcpkg
+ $(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg
+
+ Release
+ true
+
+ windows
+ osx
+ linux
+
+ $(VcpkgOSTarget)
+ win
+
+
+ false
+
+ x64
+ $(Platform)
+
+ $(VcpkgArtifactsRoot)\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\natives
+ $(VcpkgInstalledDirBase)
+ $(VcpkgInstalledDir)-static
+
+ $(VcpkgInstalledDirBase)-static\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)
+ $(VcpkgOutputPath_Static)-static
+ <_VcpkgStatusFile>$(VcpkgInstalledDir)\vcpkg\status
+
+
+
+
+
+ <_ZVcpkgInstallManifestDependenciesInputs Include="natives-ports\**;natives-triplets\**" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VcpkgPlatformTarget)-$(VcpkgOSTarget)
+ $(VcpkgTriplet)-dynamic
+
+ <_ZVcpkgMSBuildStampFile>$(_ZVcpkgInstalledDir).msbuildstamp-$(VcpkgTriplet).$(_ZVcpkgHostTripletSuffix)stamp
+
+
+ $(VcpkgInstalledDir)\$(VcpkgTriplet)
+
+
+
+ <_LibArchs Include="x64;arm64">
+ %(NativeLibSet.Identity)
+
+
+ <_BuiltRid Include="win-%(_LibArchs.Identity)">
+ %(_LibArchs.Identity)-windows\bin\%(_LibArchs.LibName)
+ %(_LibArchs.Identity)-windows-static\lib\%(_LibArchs.LibName)
+ dll
+
+
+ <_BuiltRid Include="linux-%(_LibArchs.Identity)">
+ %(_LibArchs.Identity)-linux-dynamic/lib/lib%(_LibArchs.LibName)
+ %(_LibArchs.Identity)-linux/lib/lib%(_LibArchs.LibName)
+ so
+
+
+ <_BuiltRid Include="linux-musl-%(_LibArchs.Identity)">
+ %(_LibArchs.Identity)-linux-musl-dynamic/lib/lib%(_LibArchs.LibName)
+ %(_LibArchs.Identity)-linux-musl/lib/lib%(_LibArchs.LibName)
+ so
+
+
+ <_BuiltRid Include="osx-%(_LibArchs.Identity)">
+ %(_LibArchs.Identity)-osx-dynamic/lib/lib%(_LibArchs.LibName)
+ %(_LibArchs.Identity)-osx/lib/lib%(_LibArchs.LibName)
+ dylib
+
+
+ <_BuiltRid Remove="%(Identity)" Condition="'$(_IsPackingNative)' != 'true' and '%(Identity)' != '$(VcpkgBuildOS)-$(VcpkgPlatformTarget)'" />
+
+
+
+
+
+
+
+
+
+ <_FullVcpkgRoot>$([System.IO.Path]::GetFullPath('$(VcpkgRoot)'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(NativesRuntime.Filename)%(NativesRuntime.Extension)
+ PreserveNewest
+
+
+
+
+
+
+
+
+ runtimes\%(_BuiltRid.Identity)\native\
+
+
+ runtimes\%(_BuiltRid.Identity)\native\
+
+
+
+
+
+
+
+
+
+
+ <_BuiltRidBinDir Include="$([System.IO.Path]::GetFullPath('$(VcpkgArtifactsRoot)/%(_BuiltRid.Identity)/natives/'))$([System.IO.Path]::GetDirectoryName('%(_BuiltRid.BinPath)'))" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ScopedSymlinksToRemove Include="@(_RawScopedSymlinks)" Condition="'@(_RawScopedSymlinks)' != ''" />
+
+
+
+
+
+
+
+ staticlibs\%(_BuiltRid.Identity)\
+
+
+
+
+
+
+ <_RuntimesPath Include="$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(VcpkgOutputPath)'))" />
+
+
+
+
+
+
+ <_StaticFullPath Include="$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(VcpkgOutputPath_Static)'))" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @(StatusLines, '
')
+
+
+
+
+ <_VcpkgPkg Include="@(NativeLibLic)">
+
+ $([System.Text.RegularExpressions.Regex]::Match('$(StatusText)', 'Package: %(Identity)\n(?:.*\n)*?Version: (.*?)\n').Groups[1].Value)
+
+
+
+
+
+ $(PackageDescription)
(Includes: @(_VcpkgPkg->'%(Identity) v%(Version)', ', '))
+
+
+
+
+
+
+
+ PackagePerNative
+
+
+
+
+
+ NoBuild=true;_IsPackingNative=true;PackageNativeDep=%(NativeDepsPacked.Identity)
+
+
+
+
+
+
+ <_MetaRestoreSource>$([System.IO.Path]::GetFullPath('$(PackageOutputPath)'))
+ $([System.IO.Path]::GetFullPath('$(RestoreOutputPath)\meta-restore'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PackageDescription)
(Includes: @(NativeDepsPacked->'%(Identity)', ', '))
+
+
+
+
+
+
+ <_NativeLicenseSource Include="$(VcpkgOutputPath_Static)\share\%(NativeLibLic.Identity)\copyright"
+ Condition="Exists('$(VcpkgOutputPath_Static)\share\%(NativeLibLic.Identity)\copyright')">
+ $(VcpkgOutputPath_Static)\licenses\%(NativeLibLic.Identity)_LICENSE.txt
+
+
+
+
+
+
+ $(PackageId).$(PackageNativeDep)
+
+
+
+
+
+
+
+
+ true
+ %(NativesBuilt.PackPath)%(NativesBuilt.Filename)%(NativesBuilt.Extension)
+
+
+
+ true
+ licenses\%(NativeLibLic.Identity)_LICENSE.txt
+
+
+
+ true
+ build\$(PackageId).targets
+
+
+ true
+ buildTransitive\$(PackageId).targets
+
+
+
+
+
+
+
+
+
+
diff --git a/Natives/NetCord.Natives/NetCord.Natives.local.targets b/Natives/NetCord.Natives/NetCord.Natives.local.targets
new file mode 100644
index 000000000..df2373c40
--- /dev/null
+++ b/Natives/NetCord.Natives/NetCord.Natives.local.targets
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(_NativeStaticDir.FullPath)\lib
+ %(_NativeSharedDir.FullPath)\bin
+ %(_NativeSharedDir.FullPath)\lib
+
+
+
+
+ $(ProcessNetCordNativeAot_DependsOn);GetNetCordNativesItems
+
+
+
+ <_RunExclude Include="$(NetCordNativesSharedDir)\%(_NetCordExcluded.Identity)*.*"
+ Condition="'%(_NetCordExcluded.Identity)' != '' and '$(NetCordNativesSharedDir)' != ''" />
+ <_RunExclude Include="$(NetCordNativesSharedDir)\lib%(_NetCordExcluded.Identity)*.*"
+ Condition="'%(_NetCordExcluded.Identity)' != '' and '$(NetCordNativesSharedDir)' != ''" />
+
+ <_NativesRuntime Include="$(NetCordNativesSharedDir)\**" Condition="'$(NetCordNativesSharedDir)' != ''" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SourceItemsToCopyToOutputDirectory Remove="%(_RunExclude.FullPath)" />
+
+
+
diff --git a/Natives/NetCord.Natives/NetCord.Natives.targets b/Natives/NetCord.Natives/NetCord.Natives.targets
new file mode 100644
index 000000000..e8835ae86
--- /dev/null
+++ b/Natives/NetCord.Natives/NetCord.Natives.targets
@@ -0,0 +1,180 @@
+
+
+
+ <_NetCordNativesPackage Include="$(MSBuildThisFileName)">
+ $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\'))
+
+
+
+
+
+
+
+ <_StaticLinking Include="libsodium;sodium"
+ Condition="!$(NetCordExcludeNatives.Contains('libsodium')) and '%(DirectPInvoke.Identity)' == 'libsodium'" />
+ <_StaticLinking Include="libdave;dave"
+ Condition="!$(NetCordExcludeNatives.Contains('libdave')) and '%(DirectPInvoke.Identity)' == 'libdave'" />
+
+
+ <_StaticLinking Include="libmlspp;mlspp;libhpke;hpke;libbytes;bytes;libtls_syntax;tls_syntax"
+ Condition="!$(NetCordExcludeNatives.Contains('libdave')) and '%(DirectPInvoke.Identity)' == 'libdave'" />
+
+
+ <_StaticLinking Include="libopus;opus"
+ Condition="!$(NetCordExcludeNatives.Contains('opus')) and '%(DirectPInvoke.Identity)' == 'opus'" />
+ <_StaticLinking Include="libzstd;zstd"
+ Condition="!$(NetCordExcludeNatives.Contains('zstd')) and '%(DirectPInvoke.Identity)' == 'zstd'" />
+
+
+ <_StaticLinking Include="libcrypto;crypto"
+ Condition="!$(NetCordExcludeNatives.Contains('libdave')) and '%(DirectPInvoke.Identity)' == 'libdave'" />
+
+ <__StaticsToLink Include="@(_StaticLinking)" Condition="'%(_StaticLinking.Identity)' != ''" />
+
+
+
+ <_NetCordExcluded Include="$(NetCordExcludeNatives)" Condition="'$(NetCordExcludeNatives)' != ''" />
+ <_NetCordExcluded Include="@(_StaticLinking)"
+ Condition="'$(PublishAot)' == 'true' and '%(_StaticLinking.Identity)' != ''" />
+
+
+
+
+
+ <_CurrentSharedDir>%(_NetCordNativesPackage.PackageDir)runtimes
+ <_CurrentStaticDir>%(_NetCordNativesPackage.PackageDir)staticlibs
+
+
+
+ <_RunExclude Include="$(_CurrentSharedDir)\$(RuntimeIdentifier)\native\%(_NetCordExcluded.Identity)*.*" Condition="'%(_NetCordExcluded.Identity)' != ''" />
+ <_RunExclude Include="$(_CurrentSharedDir)\$(RuntimeIdentifier)\native\lib%(_NetCordExcluded.Identity)*.*" Condition="'%(_NetCordExcluded.Identity)' != ''" />
+
+ <_NativesRuntime Include="$(_CurrentSharedDir)\$(RuntimeIdentifier)\native\**" />
+
+
+
+
+
+ <_RunExclude Include="$(_CurrentSharedDir)\*\native\%(_NetCordExcluded.Identity)*.*" Condition="'%(_NetCordExcluded.Identity)' != ''" />
+ <_RunExclude Include="$(_CurrentSharedDir)\*\native\lib%(_NetCordExcluded.Identity)*.*" Condition="'%(_NetCordExcluded.Identity)' != ''" />
+
+ <_NativesRuntime Include="$(_CurrentSharedDir)\*\native\**" />
+
+
+
+
+
+
+
+ $(ProcessNetCordNativeAot_DependsOn);GetNetCordNativesItems_PerPackage
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ <_CopiedNonNetCord Include="@(ReferenceCopyLocalPaths)"
+ Exclude="@(_NativesRuntime)" />
+ <_CopiedNonNetCord Include="@(_SourceItemsToCopyToOutputDirectory)"
+ Exclude="@(_NativesRuntime)" />
+
+ <_CopiedNatives Include="@(ReferenceCopyLocalPaths)"
+ Exclude="@(_CopiedNonNetCord)" />
+ <_CopiedNatives Include="@(_SourceItemsToCopyToOutputDirectory)"
+ Exclude="@(_CopiedNonNetCord)" />
+
+ <_NativesShared Include="$(OutDir)%(_CopiedNatives.DestinationSubDirectory)%(_CopiedNatives.Filename)%(_CopiedNatives.Extension)">
+ %(_CopiedNatives.DestinationSubDirectory)
+
+
+ <_Symlink Include="@(_NativesShared)"
+ Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Filename)%(Extension)', '\.so\.\d+'))">
+ %(Filename)%(Extension)
+ $([System.Text.RegularExpressions.Regex]::Match('%(Filename)%(Extension)', '.*?\.so\.\d+').Value)
+ $([System.Text.RegularExpressions.Regex]::Replace('%(Filename)%(Extension)', '\.so\..*', '.so'))
+
+ <_Symlink Include="@(_NativesShared)"
+ Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Filename)%(Extension)', '\.dylib$'))">
+ %(Filename)%(Extension)
+ $([System.Text.RegularExpressions.Regex]::Replace('%(Filename)%(Extension)', '^(.*?\.\d+)\..*\.dylib$', '$1.dylib'))
+ $([System.Text.RegularExpressions.Regex]::Replace('%(Filename)%(Extension)', '\.\d+.*\.dylib$', '.dylib'))
+
+ <_Symlink Remove="%(Identity)" Condition="'%(RealName)' == '' or '%(SoName)' == '' or '%(LinkerName)' == ''" />
+ <_Symlink Remove="%(Identity)" Condition="'%(RealName)' == '%(SoName)' or '%(SoName)' == '' or '%(LinkerName)' == '' or '%(LinkerName)' == '%(RealName)'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Natives/NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch b/Natives/NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch
new file mode 100644
index 000000000..f6d3360af
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch
@@ -0,0 +1,24 @@
+diff --git a/cpp/src/frame_processors.cpp b/cpp/src/frame_processors.cpp
+index 37c8d70..5f0460c 100644
+--- a/cpp/src/frame_processors.cpp
++++ b/cpp/src/frame_processors.cpp
+@@ -13,6 +13,9 @@
+
+ #if defined(_MSC_VER)
+ #include
++#if defined(_M_ARM64)
++#include
++#endif
+ #endif
+
+ namespace discord {
+@@ -25,6 +28,9 @@ std::pair OverflowAdd(size_t a, size_t b)
+ bool didOverflow = _addcarry_u64(0, a, b, &res);
+ #elif defined(_MSC_VER) && defined(_M_IX86)
+ bool didOverflow = _addcarry_u32(0, a, b, &res);
++#elif defined(_MSC_VER) && defined(_M_ARM64)
++ res = a + b;
++ bool didOverflow = res < a;
+ #else
+ bool didOverflow = __builtin_add_overflow(a, b, &res);
+ #endif
diff --git a/Natives/NetCord.Natives/natives-ports/libdave/portfile.cmake b/Natives/NetCord.Natives/natives-ports/libdave/portfile.cmake
new file mode 100644
index 000000000..4f7517e78
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-ports/libdave/portfile.cmake
@@ -0,0 +1,32 @@
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO discord/libdave
+ REF "${VERSION}"
+ SHA512 78b4e5b8ddc6397775d403465e0da770ec7905d7913546b3aec161baf4478443e554f0ae7bd012af8bfd308639be2601d46da22c02aff2b756ff91878f1fc843
+ HEAD_REF main
+ PATCHES fix-msvc-builtin-add-overflow.patch
+)
+
+vcpkg_cmake_configure(
+ SOURCE_PATH "${SOURCE_PATH}/cpp"
+ OPTIONS
+ -DTESTING=OFF
+ -DBUILD_TESTING=OFF
+ MAYBE_UNUSED_VARIABLES
+ BUILD_TESTING
+)
+
+vcpkg_cmake_build()
+
+vcpkg_cmake_install()
+vcpkg_copy_pdbs()
+
+file(INSTALL
+ "${SOURCE_PATH}/LICENSE"
+ DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}"
+ RENAME copyright
+)
+
+# Remove redundant debug directories to comply with vcpkg policy
+file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
+file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share")
diff --git a/Natives/NetCord.Natives/natives-ports/libdave/vcpkg.json b/Natives/NetCord.Natives/natives-ports/libdave/vcpkg.json
new file mode 100644
index 000000000..9a95c5338
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-ports/libdave/vcpkg.json
@@ -0,0 +1,18 @@
+{
+ "name": "libdave",
+ "version-string": "52cd56dc550f447fb354b3a06c9e2d2e2a4309c6",
+ "license": "MIT",
+ "dependencies": [
+ "openssl",
+ "mlspp",
+ "nlohmann-json",
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ }
+ ]
+}
diff --git a/Natives/NetCord.Natives/natives-ports/mlspp/portfile.cmake b/Natives/NetCord.Natives/natives-ports/mlspp/portfile.cmake
new file mode 100644
index 000000000..7c63151f2
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-ports/mlspp/portfile.cmake
@@ -0,0 +1,45 @@
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO cisco/mlspp
+ REF "${VERSION}"
+ SHA512 5d37631e2c47daae1133ef074e60cc09ca2d395f9e11c416f829060e374051cf219d2d7fe98dae49d1d045292e07d6a09f4814a5f16e6cc05e67e7cd96f146c4
+)
+
+if(VCPKG_TARGET_IS_OSX AND EXISTS "/usr/local/include/openssl/")
+ set(VCPKG_INCLUDE_OVERRIDE "-DCMAKE_CXX_FLAGS=-I${CURRENT_INSTALLED_DIR}/include")
+endif()
+
+set(VCPKG_LIBRARY_LINKAGE static)
+
+vcpkg_cmake_get_vars(cmake_vars_file)
+include("${cmake_vars_file}")
+
+set(EXTRA_OPTIONS -DDISABLE_GREASE=ON -DTESTING=OFF -DBUILD_TESTING=OFF -DMLS_CXX_NAMESPACE="mlspp")
+if(VCPKG_HOST_IS_LINUX)
+ if(VCPKG_DETECTED_CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ # Safe for GCC: Apply both flags safely as a single quoted string
+ list(APPEND EXTRA_OPTIONS "-DCMAKE_CXX_FLAGS=-Wno-error=maybe-uninitialized -Wno-error=uninitialized")
+ else()
+ # Safe for Clang: Only apply the base uninitialized flag
+ list(APPEND EXTRA_OPTIONS "-DCMAKE_CXX_FLAGS=-Wno-error=uninitialized")
+ endif()
+endif()
+
+vcpkg_cmake_configure(
+ SOURCE_PATH "${SOURCE_PATH}"
+ OPTIONS
+ -DCMAKE_POSITION_INDEPENDENT_CODE=ON
+ ${VCPKG_INCLUDE_OVERRIDE}
+ ${EXTRA_OPTIONS}
+ MAYBE_UNUSED_VARIABLES
+ BUILD_TESTING
+)
+
+vcpkg_cmake_install()
+vcpkg_copy_pdbs()
+
+vcpkg_cmake_config_fixup(PACKAGE_NAME "MLSPP" CONFIG_PATH "share/MLSPP")
+
+# Remove redundant debug directories to comply with vcpkg policy
+file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
+file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share")
diff --git a/Natives/NetCord.Natives/natives-ports/mlspp/vcpkg.json b/Natives/NetCord.Natives/natives-ports/mlspp/vcpkg.json
new file mode 100644
index 000000000..eafa20d39
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-ports/mlspp/vcpkg.json
@@ -0,0 +1,21 @@
+{
+ "name": "mlspp",
+ "version-string": "1cc50a124a3bc4e143a787ec934280dc70c1034d",
+ "description": "Cisco MLS C++ library",
+ "dependencies": [
+ "openssl",
+ "nlohmann-json",
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-get-vars",
+ "host": true
+ }
+ ]
+}
diff --git a/Natives/NetCord.Natives/natives-triplets/arm64-linux-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/arm64-linux-dynamic.cmake
new file mode 100644
index 000000000..03934bd67
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/arm64-linux-dynamic.cmake
@@ -0,0 +1,10 @@
+set(VCPKG_TARGET_ARCHITECTURE arm64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_FIXUP_ELF_RPATH ON)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl-dynamic.cmake
new file mode 100644
index 000000000..9b0cbcd61
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl-dynamic.cmake
@@ -0,0 +1,9 @@
+set(VCPKG_TARGET_ARCHITECTURE arm64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl.cmake b/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl.cmake
new file mode 100644
index 000000000..b3ce7b56a
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/arm64-linux-musl.cmake
@@ -0,0 +1,5 @@
+set(VCPKG_TARGET_ARCHITECTURE arm64)
+set(VCPKG_CRT_LINKAGE static)
+set(VCPKG_LIBRARY_LINKAGE static)
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/arm64-osx-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/arm64-osx-dynamic.cmake
new file mode 100644
index 000000000..c86e8b8fe
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/arm64-osx-dynamic.cmake
@@ -0,0 +1,10 @@
+set(VCPKG_TARGET_ARCHITECTURE arm64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
+set(VCPKG_OSX_ARCHITECTURES arm64)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/arm64-windows.cmake b/Natives/NetCord.Natives/natives-triplets/arm64-windows.cmake
new file mode 100644
index 000000000..934e3d371
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/arm64-windows.cmake
@@ -0,0 +1,8 @@
+set(VCPKG_TARGET_ARCHITECTURE arm64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/x64-linux-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/x64-linux-dynamic.cmake
new file mode 100644
index 000000000..945c86b22
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/x64-linux-dynamic.cmake
@@ -0,0 +1,10 @@
+set(VCPKG_TARGET_ARCHITECTURE x64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_FIXUP_ELF_RPATH ON)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/x64-linux-musl-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/x64-linux-musl-dynamic.cmake
new file mode 100644
index 000000000..3a0138ebc
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/x64-linux-musl-dynamic.cmake
@@ -0,0 +1,9 @@
+set(VCPKG_TARGET_ARCHITECTURE x64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/x64-linux-musl.cmake b/Natives/NetCord.Natives/natives-triplets/x64-linux-musl.cmake
new file mode 100644
index 000000000..2e7edd0f1
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/x64-linux-musl.cmake
@@ -0,0 +1,5 @@
+set(VCPKG_TARGET_ARCHITECTURE x64)
+set(VCPKG_CRT_LINKAGE static)
+set(VCPKG_LIBRARY_LINKAGE static)
+set(VCPKG_CMAKE_SYSTEM_NAME Linux)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/x64-osx-dynamic.cmake b/Natives/NetCord.Natives/natives-triplets/x64-osx-dynamic.cmake
new file mode 100644
index 000000000..a582b3589
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/x64-osx-dynamic.cmake
@@ -0,0 +1,10 @@
+set(VCPKG_TARGET_ARCHITECTURE x64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
+set(VCPKG_OSX_ARCHITECTURES x86_64)
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/natives-triplets/x64-windows.cmake b/Natives/NetCord.Natives/natives-triplets/x64-windows.cmake
new file mode 100644
index 000000000..29ec64e3c
--- /dev/null
+++ b/Natives/NetCord.Natives/natives-triplets/x64-windows.cmake
@@ -0,0 +1,8 @@
+set(VCPKG_TARGET_ARCHITECTURE x64)
+set(VCPKG_CRT_LINKAGE dynamic)
+if(PORT STREQUAL "openssl")
+ set(VCPKG_LIBRARY_LINKAGE static)
+else()
+ set(VCPKG_LIBRARY_LINKAGE dynamic)
+endif()
+set(VCPKG_BUILD_TYPE release)
diff --git a/Natives/NetCord.Natives/vcpkg b/Natives/NetCord.Natives/vcpkg
new file mode 160000
index 000000000..89dd0f4d2
--- /dev/null
+++ b/Natives/NetCord.Natives/vcpkg
@@ -0,0 +1 @@
+Subproject commit 89dd0f4d241136b843fb55813b2f0fa6448c204d
diff --git a/Natives/NetCord.Natives/vcpkg-non-windows.targets b/Natives/NetCord.Natives/vcpkg-non-windows.targets
new file mode 100644
index 000000000..60fd36a22
--- /dev/null
+++ b/Natives/NetCord.Natives/vcpkg-non-windows.targets
@@ -0,0 +1,47 @@
+
+
+ <_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgManifestFileLocation)"/>
+ <_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgConfigurationFileLocation)"
+ Condition="Exists('$(_ZVcpkgConfigurationFileLocation)')"/>
+
+
+
+
+
+
+ <_ZVcpkgTLogFileLocation>$(TLogLocation)VcpkgInstallManifest$(VcpkgTriplet).$(_ZVcpkgHostTripletSuffix)read.1u.tlog
+
+ <_ZVcpkgExecutable Condition="Exists('$(_ZVcpkgRoot)vcpkg')">$(_ZVcpkgRoot)vcpkg
+ <_ZVcpkgExecutable Condition="'$(_ZVcpkgExecutable)' == ''">vcpkg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Natives/NetCord.Natives/vcpkg-nuget.config b/Natives/NetCord.Natives/vcpkg-nuget.config
new file mode 100644
index 000000000..f072f570e
--- /dev/null
+++ b/Natives/NetCord.Natives/vcpkg-nuget.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Natives/NetCord.Natives/vcpkg.json b/Natives/NetCord.Natives/vcpkg.json
new file mode 100644
index 000000000..bff7c3a3e
--- /dev/null
+++ b/Natives/NetCord.Natives/vcpkg.json
@@ -0,0 +1,23 @@
+{
+ "dependencies": [
+ "libdave",
+ "opus",
+ "libsodium",
+ "zstd"
+ ],
+ "vcpkg-configuration": {
+ "overlay-ports": [
+ "natives-ports"
+ ],
+ "overlay-triplets": [
+ "natives-triplets"
+ ]
+ },
+ "builtin-baseline": "89dd0f4d241136b843fb55813b2f0fa6448c204d",
+ "overrides": [
+ {
+ "name": "openssl",
+ "version": "3.0.7"
+ }
+ ]
+}
diff --git a/Natives/Tests/NativeAotApp/NativeAotApp.csproj b/Natives/Tests/NativeAotApp/NativeAotApp.csproj
new file mode 100644
index 000000000..be62c62fb
--- /dev/null
+++ b/Natives/Tests/NativeAotApp/NativeAotApp.csproj
@@ -0,0 +1,50 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+ false
+
+ true
+ true
+ true
+ true
+
+ ..\..\NetCord.Natives
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Natives/Tests/NativeAotApp/Program.cs b/Natives/Tests/NativeAotApp/Program.cs
new file mode 100644
index 000000000..c28a0a76b
--- /dev/null
+++ b/Natives/Tests/NativeAotApp/Program.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+using NetCord.Natives.Tests;
+
+Console.WriteLine("NetCord native ahead of time publish app.");
+
+Console.WriteLine($"Dave Max Supported Protocol Version: {NativeProbes.DaveMaxSupportedProtocolVersion()}");
+Console.WriteLine($"Sodium Init: {NativeProbes.SodiumInit()}. 0 = OK");
+Console.WriteLine($"Opus Version String: {Marshal.PtrToStringAnsi(NativeProbes.OpusGetVersionString())}");
+uint v = NativeProbes.ZstdVersionNumber();
+Console.WriteLine($"Zstd Version: {v / 10000}.{(v / 100) % 100}.{v % 100}");
diff --git a/Natives/Tests/NativeProbes.cs b/Natives/Tests/NativeProbes.cs
new file mode 100644
index 000000000..aff4cd3f8
--- /dev/null
+++ b/Natives/Tests/NativeProbes.cs
@@ -0,0 +1,153 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace NetCord.Natives.Tests;
+
+public static partial class NativeProbes
+{
+ [LibraryImport("libdave", EntryPoint = "daveMaxSupportedProtocolVersion")]
+ internal static partial ushort DaveMaxSupportedProtocolVersion();
+
+ [LibraryImport("libsodium", EntryPoint = "sodium_init")]
+ internal static partial int SodiumInit();
+
+ [LibraryImport("opus", EntryPoint = "opus_get_version_string")]
+ internal static partial IntPtr OpusGetVersionString();
+
+ [LibraryImport("zstd", EntryPoint = "ZSTD_versionNumber")]
+ internal static partial uint ZstdVersionNumber();
+
+ [UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "This method is only used in tests to verify native library exports and is not called in the runtime path of trimmed/AOT applications.")]
+ [UnconditionalSuppressMessage("Trimming", "IL2075:DynamicallyAccessedMembers", Justification = "This method is only used in tests to verify native library exports and is not called in the runtime path of trimmed/AOT applications.")]
+ internal static IReadOnlyList GetMissingLibraryImports(IntPtr libHandle, string libName)
+ {
+ var missingExports = new List();
+ var methods = new List<(MethodInfo Method, string? EntryPoint)>();
+
+ // typeof(NetCord.Application).Assembly ensures the NetCord assembly is loaded before scanning.
+ // Exclude the test assembly itself — its probe stubs are not real library consumers.
+ var testAssembly = Assembly.GetExecutingAssembly();
+ var netcordAssemblies = new[] { typeof(NetCord.Application).Assembly }
+ .Concat(AppDomain.CurrentDomain.GetAssemblies()
+ .Where(a => a != testAssembly && a.GetName().Name?.StartsWith("NetCord", StringComparison.OrdinalIgnoreCase) == true))
+ .DistinctBy(a => a.FullName)
+ .ToList();
+
+ Console.WriteLine($"[{libName}] Scanning {netcordAssemblies.Count} NetCord assemblies: {string.Join(", ", netcordAssemblies.Select(a => a.GetName().Name))}");
+
+ foreach (var type in netcordAssemblies.SelectMany(a => a.GetTypes()))
+ {
+ foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
+ {
+ var libraryImport = method.GetCustomAttribute();
+ if (libraryImport != null)
+ {
+ if (IsMatchingLibrary(libraryImport.LibraryName, libName))
+ {
+ methods.Add((method, libraryImport.EntryPoint));
+ }
+ continue;
+ }
+
+ var dllImport = method.GetCustomAttribute();
+ if (dllImport != null)
+ {
+ if (IsMatchingLibrary(dllImport.Value, libName))
+ {
+ methods.Add((method, dllImport.EntryPoint));
+ }
+ }
+ }
+ }
+
+ if (methods.Count == 0)
+ throw new InvalidOperationException($"No methods with [LibraryImport] or [DllImport] found for library '{libName}'.");
+
+ foreach (var item in methods.DistinctBy(m => m.EntryPoint ?? m.Method.Name))
+ {
+ // Use EntryPoint if defined, otherwise fallback to method name.
+ string exportName = item.EntryPoint ?? item.Method.Name;
+ string importSig = $"{item.Method.ReturnType.Name} {item.Method.DeclaringType!.FullName}.{item.Method.Name}({string.Join(", ", item.Method.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"))})";
+
+ if (!NativeLibrary.TryGetExport(libHandle, exportName, out _))
+ {
+ Console.WriteLine($"[{libName}] MISSING: {exportName}");
+ Console.WriteLine($" Import: {importSig}");
+ missingExports.Add(exportName);
+ }
+ else
+ {
+ Console.WriteLine($"[{libName}] Found: {exportName}");
+ Console.WriteLine($" Import: {importSig}");
+ }
+ }
+
+ return missingExports;
+ }
+
+ private static bool IsMatchingLibrary(string? attributeLibName, string searchLibName)
+ {
+ if (attributeLibName == null)
+ return false;
+
+ if (string.Equals(attributeLibName, searchLibName, StringComparison.OrdinalIgnoreCase))
+ return true;
+
+ if (attributeLibName.StartsWith("lib", StringComparison.OrdinalIgnoreCase))
+ {
+ if (string.Equals(attributeLibName.Substring(3), searchLibName, StringComparison.OrdinalIgnoreCase))
+ return true;
+ }
+ else
+ {
+ if (string.Equals("lib" + attributeLibName, searchLibName, StringComparison.OrdinalIgnoreCase))
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ * This method is not working on macOS due to System.Diagnostics.ProcessModule
+ * not listing native libraries loaded by the runtime's dynamic library loader (dyld).
+ * This is likely because dyld does not expose these libraries to the process in the
+ * same way that LoadLibrary on Windows or dlopen on Linux does, and as a result they
+ * do not appear in the list of modules for the process. This is a known limitation
+ * when trying to inspect loaded native libraries on macOS using .NET, and may require
+ * platform-specific workarounds or tools to verify the presence of native libraries
+ * on that platform.
+ */
+ internal static IntPtr GetLoadedNativeModuleHandle(string libName)
+ {
+ _ = libName switch
+ {
+ "libdave" => DaveMaxSupportedProtocolVersion(),
+ "libsodium" => SodiumInit(),
+ "opus" => OpusGetVersionString(),
+ "zstd" => (object)ZstdVersionNumber(),
+ _ => throw new InvalidOperationException($"Unknown library name '{libName}' provided to test."),
+ };
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ throw new PlatformNotSupportedException("Retrieving loaded native module handles is not supported on macOS due to platform limitations.");
+
+ var module = System.Diagnostics.Process.GetCurrentProcess().Modules
+ .Cast()
+ .FirstOrDefault(m =>
+ {
+ var moduleName = Path.GetFileName(m.FileName);
+ return moduleName.StartsWith(libName, StringComparison.OrdinalIgnoreCase)
+ || moduleName.StartsWith($"lib{libName}", StringComparison.OrdinalIgnoreCase);
+ })
+ ?? throw new InvalidOperationException($"Native module '{libName}' was not found in the current process.");
+
+ if (NativeLibrary.TryLoad(module.FileName, out var libHandleByPath))
+ {
+ Console.WriteLine($"Successfully obtained a handle for native module '{module.ModuleName}' using path '{module.FileName}'.");
+ return libHandleByPath;
+ }
+
+ throw new InvalidOperationException($"Failed to obtain a handle for native module '{module.ModuleName}'.");
+ }
+}
diff --git a/Natives/Tests/NetCord.Natives.Tests/AssemblyInfo.cs b/Natives/Tests/NetCord.Natives.Tests/AssemblyInfo.cs
new file mode 100644
index 000000000..ab8dcc1e1
--- /dev/null
+++ b/Natives/Tests/NetCord.Natives.Tests/AssemblyInfo.cs
@@ -0,0 +1,2 @@
+
+[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
diff --git a/Natives/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Natives/Tests/NetCord.Natives.Tests/NativesBuildTests.cs
new file mode 100644
index 000000000..9a6d481b0
--- /dev/null
+++ b/Natives/Tests/NetCord.Natives.Tests/NativesBuildTests.cs
@@ -0,0 +1,218 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Locator;
+using Microsoft.Build.Logging;
+
+namespace NetCord.Natives.Tests;
+
+[TestClass]
+public class NativesBuildTests
+{
+ [TestMethod]
+ [DataRow("libdave")]
+ [DataRow("libsodium")]
+ [DataRow("opus")]
+ [DataRow("zstd")]
+ public void NativesLoaded(string libName)
+ {
+ _ = libName switch
+ {
+ "libdave" => NativeProbes.DaveMaxSupportedProtocolVersion(),
+ "libsodium" => NativeProbes.SodiumInit(),
+ "opus" => NativeProbes.OpusGetVersionString(),
+ "zstd" => (object)NativeProbes.ZstdVersionNumber(),
+ _ => throw new InvalidOperationException($"Unknown library name '{libName}' provided to test."),
+ };
+ }
+
+ [TestMethod]
+ [OSCondition(ConditionMode.Exclude, OperatingSystems.OSX)]
+ [DataRow("libdave")]
+ [DataRow("libsodium")]
+ [DataRow("opus")]
+ [DataRow("zstd")]
+ public void AllLibraryImportsExistInBinary(string libName)
+ {
+ var libHandle = NativeProbes.GetLoadedNativeModuleHandle(libName);
+ var missingExports = NativeProbes.GetMissingLibraryImports(libHandle, libName);
+
+ Assert.IsEmpty(missingExports, $"The following entry points were not found in '{libName}': {string.Join(", ", missingExports)}");
+ }
+
+ [AssemblyInitialize]
+ public static void AssemblyInit(TestContext context)
+ {
+ // This is guaranteed to run before any test method
+ MSBuildLocator.RegisterDefaults();
+ }
+
+ const string NativeAotAppLogTag = nameof(NativeAotStaticLinking);
+
+ [TestMethod]
+ [DoNotParallelize]
+ [DataRow("libdave;libsodium;opus;zstd")]
+ public void NativeAotStaticLinking(string libNames)
+ {
+ MSBuildNativeAotPublish(libNames, false);
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ [DataRow("libdave;libsodium;opus;zstd")]
+ public void NativeAotStaticLinking_WithPackageVer(string libNames)
+ {
+ MSBuildNativeAotPublish(libNames, true);
+ }
+
+ private static void MSBuildNativeAotPublish(string libNames, bool testWithPackageVer)
+ {
+ // 1. Get properties from AssemblyMetadata attributes
+ var assembly = typeof(NativesBuildTests).Assembly;
+
+ var projectDirectory = assembly.GetCustomAttributes()
+ .FirstOrDefault(a => a.Key == "NativeAotAppDir")?.Value;
+ Assert.IsNotNull(projectDirectory, "NativeAotAppDir metadata attribute is not defined.");
+
+ var projectFile = Path.Combine(projectDirectory, "NativeAotApp.csproj");
+
+ var propsAttr = assembly.GetCustomAttributes()
+ .FirstOrDefault(a => a.Key == "NativeAotAppProps")?.Value;
+
+ var binlogpath = assembly.GetCustomAttributes()
+ .FirstOrDefault(a => a.Key == "NativeAotBinLogPath")?.Value;
+
+ var configuration = assembly.GetCustomAttribute()?.Configuration ?? "Debug";
+
+ // 2. Parse MSBuild Global Properties into a Dictionary
+ var globalProperties = new Dictionary
+ {
+ { "Configuration", configuration }
+ };
+
+ var pairs = propsAttr?.Split([';', ','], StringSplitOptions.RemoveEmptyEntries) ?? [];
+ foreach (var pair in pairs)
+ {
+ var kvp = pair.Split('=');
+ if (kvp.Length == 2)
+ {
+ globalProperties[kvp[0].Trim()] = kvp[1].Trim();
+ }
+ }
+
+ // 3. Set up Loggers (Console + optional Binary Logger)
+ var loggers = new List
+ {
+ new ConsoleLogger(Enum.Parse(Environment.GetEnvironmentVariable("DotnetVerbose") ?? "Minimal", true),
+ msg => Console.WriteLine($"[{NativeAotAppLogTag}/Publish] {msg.Trim()}"), null, null)
+ };
+
+ if (!string.IsNullOrEmpty(binlogpath))
+ {
+ var withverbinlogpath = Path.GetFileNameWithoutExtension(binlogpath) + (testWithPackageVer ? "_with_pkg_ver" : "") + Path.GetExtension(binlogpath);
+ loggers.Add(new BinaryLogger { Parameters = testWithPackageVer ? withverbinlogpath : binlogpath });
+ }
+
+ var buildParameters = new BuildParameters
+ {
+ Loggers = loggers,
+ EnableNodeReuse = false,
+ };
+
+ if (testWithPackageVer)
+ // Get the version of NetCord.Natives from the project file
+ using (var prjVerCollection = new ProjectCollection())
+ {
+ var prjPath = assembly.GetCustomAttributes()
+ .FirstOrDefault(a => a.Key == "NetCordNativesPath")?.Value;
+ Assert.IsNotNull(prjPath, "NetCordNativesPath metadata attribute is not defined.");
+
+ var prjVerInstance = new ProjectInstance(prjPath, globalProperties, null, prjVerCollection);
+ var prjVerRequest = new BuildRequestData(prjVerInstance, ["GetAssemblyVersion"]);
+
+ var prjVerResult = BuildManager.DefaultBuildManager.Build(buildParameters, prjVerRequest);
+ Assert.AreEqual(BuildResultCode.Success, prjVerResult.OverallResult, $"Failed to get NetCord.Natives version from '{prjPath}'.");
+
+ var prjVer = prjVerInstance.GetPropertyValue("Version");
+ globalProperties["TestWithPackageVer"] = prjVer;
+
+ Console.WriteLine($"[{NativeAotAppLogTag}/Publish] Using NetCord.Natives version '{prjVer}' for PackageReference testing.");
+ }
+
+ // Clear internal MSBuild engine caches
+ BuildManager.DefaultBuildManager.ResetCaches();
+
+ // Evaluate and Execute the "Restore" target first
+ Console.WriteLine($"[{NativeAotAppLogTag}/Publish] Restoring Native AoT app dependencies...");
+
+ using (var restoreCollection = new ProjectCollection())
+ {
+ var restoreInstance = new ProjectInstance(projectFile, globalProperties, null, restoreCollection);
+ var restoreRequest = new BuildRequestData(restoreInstance, ["Restore"]);
+
+ var restoreResult = BuildManager.DefaultBuildManager.Build(buildParameters, restoreRequest);
+ Assert.AreEqual(BuildResultCode.Success, restoreResult.OverallResult, $"Native AoT restore failed for '{libNames}'.");
+ }
+
+ // Clear internal MSBuild engine caches so the next build sees the restored assets
+ BuildManager.DefaultBuildManager.ResetCaches();
+
+ // Evaluate and Execute the "Publish" target programmatically
+ Console.WriteLine($"[{NativeAotAppLogTag}/Publish] Building and Publishing Native AoT app in ({projectDirectory}) via MSBuild API...");
+
+ // We use a fresh collection so it reads the newly generated project.assets.json from disk
+ using var publishCollection = new ProjectCollection();
+ var publishInstance = new ProjectInstance(projectFile, globalProperties, null, publishCollection);
+ var publishRequest = new BuildRequestData(publishInstance, ["Publish"]);
+
+ var buildResult = BuildManager.DefaultBuildManager.Build(buildParameters, publishRequest);
+
+ // Assert build success
+ Assert.AreEqual(BuildResultCode.Success, buildResult.OverallResult, $"Native AoT build failed for '{libNames}'.");
+
+ // Instantly extract the 'PublishDir' property from the freshly evaluated project state
+ var publishDirProperty = publishInstance.GetPropertyValue("PublishDir");
+ Assert.IsFalse(string.IsNullOrEmpty(publishDirProperty), $"PublishDir is empty for '{libNames}'.");
+
+ // sanitize back-slash
+ publishDirProperty = publishDirProperty.Replace('\\', Path.DirectorySeparatorChar);
+
+ var runCmdOutput = Path.GetFullPath(Path.Combine(projectDirectory, publishDirProperty,
+ "NativeAotApp" + (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "")));
+
+ Console.WriteLine($"[{NativeAotAppLogTag}/Publish] Native AoT app published to: '{runCmdOutput}'");
+
+ // Execute the generated Native AOT Binary
+ var aotProcess = new System.Diagnostics.Process();
+ aotProcess.StartInfo.FileName = runCmdOutput;
+ aotProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(runCmdOutput);
+
+ Console.WriteLine($"[{NativeAotAppLogTag}/Run] Running Native AoT app: '{runCmdOutput}'");
+
+ aotProcess.StartInfo.RedirectStandardOutput = true;
+ aotProcess.OutputDataReceived += (sender, e) =>
+ {
+ if (!string.IsNullOrEmpty(e.Data))
+ Console.WriteLine($"[{NativeAotAppLogTag}/Run] {e.Data}");
+ };
+ aotProcess.StartInfo.RedirectStandardError = true;
+ aotProcess.ErrorDataReceived += (sender, e) =>
+ {
+ if (!string.IsNullOrEmpty(e.Data))
+ Console.Error.WriteLine($"[{NativeAotAppLogTag}/Run] {e.Data}");
+ };
+
+ aotProcess.Start();
+ aotProcess.BeginOutputReadLine();
+ aotProcess.BeginErrorReadLine();
+
+ if (!aotProcess.HasExited)
+ aotProcess.WaitForExit();
+
+ Assert.AreEqual(0, aotProcess.ExitCode, $"Native AoT app failed to run for '{libNames}'.");
+ }
+}
diff --git a/Natives/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj b/Natives/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj
new file mode 100644
index 000000000..3efa62409
--- /dev/null
+++ b/Natives/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj
@@ -0,0 +1,77 @@
+
+
+
+ net10.0
+ enable
+ enable
+ true
+
+ false
+ true
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+ ..\..\NetCord.Natives\
+ NetCordNativesDir=$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(NetCordNativesDir)'))
+
+ $(VCPKG_ROOT)
+ $(NativeAotAppProps);VcpkgRoot=$(VcpkgRoot)
+
+ $(NativeAotAppProps);$(AppendNativeAotAppProps)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Parameter1>NativeAotAppDir
+ <_Parameter2>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/../NativeAotApp'))
+
+
+ <_Parameter1>NativeAotAppProps
+ <_Parameter2>$(NativeAotAppProps)
+
+
+ <_Parameter1>NativeAotBinLogPath
+ <_Parameter2>$(NativeAotBinLogPath)
+
+
+ <_Parameter1>NetCordNativesPath
+ <_Parameter2>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/$(NetCordNativesDir)/NetCord.Natives.csproj'))
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index b3d29496c..3e12cda4e 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ You can install NetCord packages via NuGet package manager:
| **[NetCord.Hosting](https://www.nuget.org/packages/NetCord.Hosting)** | Provides .NET Generic Host extensions for the NetCord package. |
| **[NetCord.Hosting.Services](https://www.nuget.org/packages/NetCord.Hosting.Services)** | Provides .NET Generic Host extensions for the NetCord.Services package. |
| **[NetCord.Hosting.AspNetCore](https://www.nuget.org/packages/NetCord.Hosting.AspNetCore)** | Provides ASP.NET Core extensions for seamless handling of HTTP events. |
+| **[NetCord.Natives](https://www.nuget.org/packages/NetCord.Natives)** | Provides pre-built native dependency library binaries.
[See Native Dependencies Installation Guide.](https://netcord.dev/guides/basic-concepts/installing-native-dependencies.html) |
## 2. 🚀 Showcase
@@ -116,6 +117,8 @@ NetCord's goal is to allow .NET developers to create fully customizable Discord
This repository is released under the [MIT License](LICENSE.md).
+The use of NetCord.Natives may subject to each libraries licenses.
+
## 9. 🛠️ Development
### Versioning
diff --git a/Resources/NuGet/README.md b/Resources/NuGet/README.md
index 89a1d4146..617844cf9 100644
--- a/Resources/NuGet/README.md
+++ b/Resources/NuGet/README.md
@@ -25,6 +25,7 @@ You can install NetCord packages via NuGet package manager:
| **[NetCord.Hosting](https://www.nuget.org/packages/NetCord.Hosting)** | Provides .NET Generic Host extensions for the NetCord package. |
| **[NetCord.Hosting.Services](https://www.nuget.org/packages/NetCord.Hosting.Services)** | Provides .NET Generic Host extensions for the NetCord.Services package. |
| **[NetCord.Hosting.AspNetCore](https://www.nuget.org/packages/NetCord.Hosting.AspNetCore)** | Provides ASP.NET Core extensions for seamless handling of HTTP events. |
+| NetCord.Natives.<RuntimeId> | Provides pre-built native runtime dependencies binary.
[See Native Dependencies Installation Guide.](https://netcord.dev/guides/basic-concepts/installing-native-dependencies.html) |
## 2. 🚀 Showcase
@@ -95,6 +96,8 @@ NetCord's goal is to allow .NET developers to create fully customizable Discord
This repository is released under the [MIT License](https://github.com/NetCordDev/NetCord/blob/alpha/LICENSE.md).
+The use of NetCord.Natives may subject to each libraries licenses.
+
## 9. 🛠️ Development
### Versioning
diff --git a/flake.nix b/flake.nix
index f9954b91e..028bf8c58 100644
--- a/flake.nix
+++ b/flake.nix
@@ -36,7 +36,17 @@
dotnet-sdk = dotnet;
};
+ nuget = pkgs.runCommand "unwrapped-nuget" {} ''
+ mkdir -p $out/bin
+ install -m 755 ${pkgs.nuget}/lib/Nuget/nuget.exe $out/bin/nuget
+ '';
+
dotnetRoot = "${dotnet.unwrapped}/share/dotnet";
+
+ darwinPackages = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isDarwin (with pkgs; [
+ libiconv
+ apple-sdk
+ ]);
in
{
default = pkgs.mkShell {
@@ -47,6 +57,85 @@
DOTNET_ROOT = dotnetRoot;
};
+ natives = pkgs.mkShell.override {
+ stdenv = if pkgs.clangStdenv.isLinux then
+ pkgs.clangStdenv
+ else pkgs.clangStdenv.override (old: {
+ hostPlatform = old.hostPlatform // { darwinMinVersion = "12.0"; };
+ targetPlatform = old.targetPlatform // { darwinMinVersion = "12.0"; };
+ });
+ } ({
+ packages = [
+ dotnet
+ nuget
+ pkgs.mono
+ pkgs.vcpkg-tool
+ pkgs.cmake
+ pkgs.ninja
+ pkgs.pkg-config
+ pkgs.autoconf
+ pkgs.autoconf-archive
+ pkgs.automake
+ pkgs.libtool
+ pkgs.git
+ pkgs.zip
+ pkgs.unzip
+ pkgs.perl
+ pkgs.curl
+ ] ++ darwinPackages;
+
+ DOTNET_ROOT = dotnetRoot;
+
+ VCPKG_FORCE_SYSTEM_BINARIES = "1";
+
+ shellHook = ''
+ export VCPKG_ROOT="$PWD/Natives/NetCord.Natives/vcpkg"
+
+ ln -sf ${pkgs.vcpkg-tool}/bin/vcpkg $VCPKG_ROOT/vcpkg
+ '';
+ } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
+ SDKROOT = "${pkgs.apple-sdk}/SDKs/MacOSX.sdk";
+ MACOSX_DEPLOYMENT_TARGET = "12.0";
+ VCPKG_ENV_PASSTHROUGH = "MACOSX_DEPLOYMENT_TARGET,SDKROOT";
+ });
+
+ natives-musl = pkgs.mkShell.override {
+ stdenv = pkgs.pkgsMusl.clangStdenv;
+ } ({
+ packages = [
+ dotnet
+ nuget
+ pkgs.mono
+ pkgs.vcpkg-tool
+ pkgs.cmake
+ pkgs.ninja
+ pkgs.pkg-config
+ pkgs.autoconf
+ pkgs.autoconf-archive
+ pkgs.automake
+ pkgs.libtool
+ pkgs.git
+ pkgs.zip
+ pkgs.unzip
+ pkgs.perl
+ pkgs.curl
+ ] ++ darwinPackages;
+
+ DOTNET_ROOT = dotnetRoot;
+
+ VCPKG_FORCE_SYSTEM_BINARIES = "1";
+
+ shellHook = ''
+ export VCPKG_ROOT="$PWD/Natives/NetCord.Natives/vcpkg"
+
+ ln -sf ${pkgs.vcpkg-tool}/bin/vcpkg $VCPKG_ROOT/vcpkg
+ '';
+ } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
+ SDKROOT = "${pkgs.apple-sdk}/SDKs/MacOSX.sdk";
+ MACOSX_DEPLOYMENT_TARGET = "12.0";
+ VCPKG_ENV_PASSTHROUGH = "MACOSX_DEPLOYMENT_TARGET,SDKROOT";
+ });
+
docs = pkgs.mkShell {
packages = [
docfx