From 9638b170a3e66023a5bccd729061a7e68e9f0780 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:58:51 +0900 Subject: [PATCH 01/16] Pivot to use vcpkg to build natives * put into nuget package --- .gitmodules | 3 + NetCord.Natives/.gitignore | 1 + NetCord.Natives/NetCord.Natives.csproj | 80 +++++++++++++++++++ NetCord.Natives/NetCord.Natives.props | 7 ++ NetCord.Natives/NetCord.Natives.targets | 42 ++++++++++ .../natives-ports/libdave/portfile.cmake | 29 +++++++ .../natives-ports/libdave/vcpkg.json | 18 +++++ .../natives-ports/mlspp/portfile.cmake | 29 +++++++ .../natives-ports/mlspp/vcpkg.json | 17 ++++ NetCord.Natives/vcpkg | 1 + NetCord.Natives/vcpkg.json | 12 +++ NetCord.slnx | 1 + 12 files changed, 240 insertions(+) create mode 100644 .gitmodules create mode 100644 NetCord.Natives/.gitignore create mode 100644 NetCord.Natives/NetCord.Natives.csproj create mode 100644 NetCord.Natives/NetCord.Natives.props create mode 100644 NetCord.Natives/NetCord.Natives.targets create mode 100644 NetCord.Natives/natives-ports/libdave/portfile.cmake create mode 100644 NetCord.Natives/natives-ports/libdave/vcpkg.json create mode 100644 NetCord.Natives/natives-ports/mlspp/portfile.cmake create mode 100644 NetCord.Natives/natives-ports/mlspp/vcpkg.json create mode 160000 NetCord.Natives/vcpkg create mode 100644 NetCord.Natives/vcpkg.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..c33f058f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "NetCord.Natives/vcpkg"] + path = NetCord.Natives/vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/NetCord.Natives/.gitignore b/NetCord.Natives/.gitignore new file mode 100644 index 00000000..07db887c --- /dev/null +++ b/NetCord.Natives/.gitignore @@ -0,0 +1 @@ +*.tlog diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj new file mode 100644 index 00000000..37804cd0 --- /dev/null +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -0,0 +1,80 @@ +ο»Ώ + + + Pre-built binaries for NetCord, $(Description) + false + + bin\natives + vcpkg/scripts/buildsystems/msbuild/vcpkg + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..')) + + + + + + + vcpkg\%(Filename)%(Extension) + + + + + + + + true + + windows + x64 + $(Platform) + + debug + $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)\$(DebugDefinedDir) + + + + + Built Natives $(DebugDefinedDir)\%(RecursiveDir)%(Filename)%(Extension) + + + + + + + + + + + + + + + + + + + + + + + + + + %(RecursiveDir)%(FileName)%(Extension) + true + runtimes\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\$(DebugDefinedDir)\ + + + + true + build\ + + + + + + + + + + diff --git a/NetCord.Natives/NetCord.Natives.props b/NetCord.Natives/NetCord.Natives.props new file mode 100644 index 00000000..ecee165d --- /dev/null +++ b/NetCord.Natives/NetCord.Natives.props @@ -0,0 +1,7 @@ + + + + $(MSBuildThisFileDirectory)..\runtimes\ + + + diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets new file mode 100644 index 00000000..c65c04f8 --- /dev/null +++ b/NetCord.Natives/NetCord.Natives.targets @@ -0,0 +1,42 @@ + + + + + + true + true + true + + true + true + true + + true + + <_NetCordNativesPath>$(NetCordNativesPath)\$(RuntimeIdentifier) + + + + + + + + + + %(NativeFilter.Link) + %(Filename)%(Extension) + PreserveNewest + + + + + + + + + + + + diff --git a/NetCord.Natives/natives-ports/libdave/portfile.cmake b/NetCord.Natives/natives-ports/libdave/portfile.cmake new file mode 100644 index 00000000..8568d022 --- /dev/null +++ b/NetCord.Natives/natives-ports/libdave/portfile.cmake @@ -0,0 +1,29 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO discord/libdave + REF "${VERSION}" + SHA512 78b4e5b8ddc6397775d403465e0da770ec7905d7913546b3aec161baf4478443e554f0ae7bd012af8bfd308639be2601d46da22c02aff2b756ff91878f1fc843 + HEAD_REF main +) + +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(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") + +# file(INSTALL +# "${SOURCE_PATH}/LICENSE" +# DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" +# RENAME LICENSE.txt +# ) \ No newline at end of file diff --git a/NetCord.Natives/natives-ports/libdave/vcpkg.json b/NetCord.Natives/natives-ports/libdave/vcpkg.json new file mode 100644 index 00000000..9f74f4d3 --- /dev/null +++ b/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 + } + ] +} \ No newline at end of file diff --git a/NetCord.Natives/natives-ports/mlspp/portfile.cmake b/NetCord.Natives/natives-ports/mlspp/portfile.cmake new file mode 100644 index 00000000..66dd943c --- /dev/null +++ b/NetCord.Natives/natives-ports/mlspp/portfile.cmake @@ -0,0 +1,29 @@ +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_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + ${VCPKG_INCLUDE_OVERRIDE} + -DDISABLE_GREASE=ON + -DTESTING=OFF + -DBUILD_TESTING=OFF + -DMLS_CXX_NAMESPACE="mlspp" + MAYBE_UNUSED_VARIABLES + BUILD_TESTING +) + +vcpkg_cmake_install() +vcpkg_copy_pdbs() + +vcpkg_cmake_config_fixup(PACKAGE_NAME "MLSPP" CONFIG_PATH "share/MLSPP") diff --git a/NetCord.Natives/natives-ports/mlspp/vcpkg.json b/NetCord.Natives/natives-ports/mlspp/vcpkg.json new file mode 100644 index 00000000..fca86978 --- /dev/null +++ b/NetCord.Natives/natives-ports/mlspp/vcpkg.json @@ -0,0 +1,17 @@ +{ + "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 + } + ] +} diff --git a/NetCord.Natives/vcpkg b/NetCord.Natives/vcpkg new file mode 160000 index 00000000..89dd0f4d --- /dev/null +++ b/NetCord.Natives/vcpkg @@ -0,0 +1 @@ +Subproject commit 89dd0f4d241136b843fb55813b2f0fa6448c204d diff --git a/NetCord.Natives/vcpkg.json b/NetCord.Natives/vcpkg.json new file mode 100644 index 00000000..426671ba --- /dev/null +++ b/NetCord.Natives/vcpkg.json @@ -0,0 +1,12 @@ +{ + "dependencies": [ + "libdave", + "opus", + "libsodium" + ], + "vcpkg-configuration": { + "overlay-ports": [ + "natives-ports" + ] + } +} diff --git a/NetCord.slnx b/NetCord.slnx index 23417afd..fd20607e 100644 --- a/NetCord.slnx +++ b/NetCord.slnx @@ -97,6 +97,7 @@ + From f5c24ebb270b7962b5e1dd8189a10b4c3cf71d70 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Thu, 30 Apr 2026 00:38:00 +0900 Subject: [PATCH 02/16] * Add NetCord.Natives project and vcpkg support * Add native ports for libdave and mlspp * Update build workflows for native packaging * Add local targets and CI helpers for natives * Update README --- .github/workflows/build-and-publish.yml | 85 +++------- .github/workflows/build-natives.yml | 143 ++++++++++++++++ .github/workflows/build.yml | 1 + NetCord.Natives/NetCord.Natives.csproj | 159 ++++++++++++++---- NetCord.Natives/NetCord.Natives.local.targets | 17 ++ NetCord.Natives/NetCord.Natives.props | 10 +- NetCord.Natives/NetCord.Natives.targets | 44 ++--- .../natives-ports/libdave/portfile.cmake | 12 +- README.md | 3 + Resources/NuGet/README.md | 3 + 10 files changed, 337 insertions(+), 140 deletions(-) create mode 100644 .github/workflows/build-natives.yml create mode 100644 NetCord.Natives/NetCord.Natives.local.targets diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 96ee3621..a27c0d24 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -7,15 +7,25 @@ on: - "[0-9]+.[0-9]+.[0-9]+-*" jobs: - build-and-publish: + build: + uses: ./.github/workflows/build.yml + + publish: + needs: build runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Download Build Artifacts + uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + with: + name: Build Artifacts + path: artifacts/build + + - name: Download Documentation Artifacts + uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a 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 @@ -24,76 +34,25 @@ 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/build/NetCord/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate + dotnet nuget push artifacts/build/NetCord.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate + dotnet nuget push artifacts/build/Hosting/NetCord.Hosting/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate + dotnet nuget push artifacts/build/Hosting/NetCord.Hosting.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate + dotnet nuget push artifacts/build/Hosting/NetCord.Hosting.AspNetCore/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate - name: Deploy Documentation - uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0 + uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 with: username: ${{ secrets.SSH_USERNAME }} host: ${{ secrets.SSH_HOST }} port: ${{ secrets.SSH_PORT }} key: ${{ secrets.SSH_KEY }} rm: true - source: Documentation/_site + source: artifacts/docs strip_components: 2 target: ~/NetCord/html - - - 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 00000000..ed3496f2 --- /dev/null +++ b/.github/workflows/build-natives.yml @@ -0,0 +1,143 @@ +name: Build NetCord.Natives + +on: + workflow_dispatch: {} + push: + paths: + - 'NetCord.Natives/**' + +jobs: + build-natives: + runs-on: ${{ matrix.runs-on }} + env: + CI: true + VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite + VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads + strategy: + fail-fast: false + matrix: + include: + - rid: win-x64 + runs-on: windows-latest + vcpkg-os-target: windows + vcpkg-platform-target: x64 + - rid: win-arm64 + runs-on: windows-latest + vcpkg-os-target: windows + vcpkg-platform-target: arm64 + - rid: osx-x64 + runs-on: macos-latest + vcpkg-os-target: osx + vcpkg-platform-target: x64 + - rid: osx-arm64 + runs-on: macos-latest + vcpkg-os-target: osx + vcpkg-platform-target: arm64 + - rid: linux-x64 + runs-on: ubuntu-latest + vcpkg-os-target: linux + vcpkg-platform-target: x64 + - rid: linux-arm64 + runs-on: ubuntu-latest + vcpkg-os-target: linux + vcpkg-platform-target: arm64 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache vcpkg installs + uses: actions/cache@v4 + with: + path: | + .vcpkg-cache + .vcpkg-downloads + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json') }} + restore-keys: | + vcpkg-${{ runner.os }}-${{ matrix.rid }}- + vcpkg-${{ runner.os }}- + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Resolve vcpkg from runner image + shell: pwsh + run: | + $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT + if (-not $vcpkgRoot) { + $vcpkgCommand = Get-Command vcpkg -ErrorAction Stop + $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source + } + + if (-not (Test-Path $vcpkgRoot)) { + throw "vcpkg installation root not found." + } + + "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + "VcpkgMsbuildPath=$vcpkgRoot/scripts/buildsystems/msbuild/vcpkg" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Restore + shell: pwsh + run: | + dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + + - name: Build native outputs for ${{ matrix.rid }} + shell: pwsh + run: | + dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + + - name: List artifacts + shell: pwsh + run: | + Get-ChildItem -Recurse NetCord.Natives/bin | Select-Object FullName + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.rid }} + path: NetCord.Natives/bin + + pack-natives: + needs: build-natives + runs-on: ubuntu-latest + env: + CI: true + NativeArtifactsRoot: ${{ github.workspace }}/artifacts + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download native artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: false + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Resolve native license root + shell: pwsh + run: | + $licenseRoot = Get-ChildItem artifacts -Directory | Sort-Object Name | Select-Object -First 1 + if (-not $licenseRoot) { + throw "No native artifact directories were downloaded." + } + + "NativeLicenseRoot=$($licenseRoot.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Pack combined nupkg + shell: pwsh + run: | + dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:NativeArtifactsRoot=$env:NativeArtifactsRoot -p:NativeLicenseRoot=$env:NativeLicenseRoot -o artifacts/package + + - name: Upload nupkg + uses: actions/upload-artifact@v4 + with: + name: NetCord.Natives.Package + path: artifacts/package/*.nupkg diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 350387e0..40c35ec0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,7 @@ name: Build on: + workflow_call: pull_request: branches: - stable diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 37804cd0..ef8e1acb 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -1,45 +1,63 @@ ο»Ώ - Pre-built binaries for NetCord, $(Description) + Pre-built native libraries for NetCord, $(Description) false - bin\natives - vcpkg/scripts/buildsystems/msbuild/vcpkg $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..')) - - + + vcpkg\%(Filename)%(Extension) - - + debug + $(MSBuildProjectDirectory)\artifacts + + vcpkg/scripts/buildsystems/msbuild/vcpkg true - windows + windows + osx + linux + x64 $(Platform) - debug - $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)\$(DebugDefinedDir) + bin\natives + $(VcpkgInstalledDir)-static + + $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget) + $(VcpkgInstalledDir)-static\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static + $(BuildNativeOutputPath) + + ClCompile;_CopyNativeLicenses - - Built Natives $(DebugDefinedDir)\%(RecursiveDir)%(Filename)%(Extension) - + + + + + + + <_NetCordStaticFullPath Include="$([System.IO.Path]::GetFullPath('$(BuildNativeStaticOutputPath)'))" /> + + + + + - + @@ -47,34 +65,111 @@ - + + + + + + + + + + + + <_NativeLicenseSource Include="$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright" Condition="Exists('$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright')"> + $(BuildNativeOutputPath)\licenses\%(AllowedNativesLicenses.Identity)_LICENSE.txt + + + + - + + + + + + %(Filename)%(Extension) + PreserveNewest + + + + + + + $(PackageId).$(VcpkgOSTarget)-$(VcpkgPlatformTarget) + + + + runtimes\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\native\%(Filename)%(Extension) + + + runtimes-static\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\%(Filename)%(Extension) + + + + + <_NativeRuntime Include="win-x64"> + runtimes\win-x64\native\ + runtimes-static\win-x64\ + + <_NativeRuntime Include="win-arm64"> + runtimes\win-arm64\native\ + runtimes-static\win-arm64\ + + <_NativeRuntime Include="osx-x64"> + runtimes\osx-x64\native\ + runtimes-static\osx-x64\ + + <_NativeRuntime Include="osx-arm64"> + runtimes\osx-arm64\native\ + runtimes-static\osx-arm64\ + + <_NativeRuntime Include="linux-x64"> + runtimes\linux-x64\native\ + runtimes-static\linux-x64\ + + <_NativeRuntime Include="linux-arm64"> + runtimes\linux-arm64\native\ + runtimes-static\linux-arm64\ + + + + %(_NativeRuntime.PackageRuntimePath)%(Filename)%(Extension) + + + %(_NativeRuntime.PackageStaticPath)%(Filename)%(Extension) + + - - - - + + true + %(NativesBuilt.TargetPath) + - - %(RecursiveDir)%(FileName)%(Extension) + true - runtimes\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\$(DebugDefinedDir)\ + licenses\ - - + + <_BuildFiles Include="$(MSBuildProjectName).props;$(MSBuildProjectName).targets"> true - build\ + + + + build\$(PackageId)%(Extension) + + + buildTransitive\$(PackageId)%(Extension) - - - - - + + + + + diff --git a/NetCord.Natives/NetCord.Natives.local.targets b/NetCord.Natives/NetCord.Natives.local.targets new file mode 100644 index 00000000..1c79590d --- /dev/null +++ b/NetCord.Natives/NetCord.Natives.local.targets @@ -0,0 +1,17 @@ + + + + + + + + + + + + @(_NetCordStaticDir->'%(Identity)')\lib + + + + + diff --git a/NetCord.Natives/NetCord.Natives.props b/NetCord.Natives/NetCord.Natives.props index ecee165d..021708eb 100644 --- a/NetCord.Natives/NetCord.Natives.props +++ b/NetCord.Natives/NetCord.Natives.props @@ -1,7 +1,7 @@ - - - $(MSBuildThisFileDirectory)..\runtimes\ - - + + + $(MSBuildThisFileDirectory)..\runtimes-static\$(RuntimeIdentifier) + + diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets index c65c04f8..16d61ae6 100644 --- a/NetCord.Natives/NetCord.Natives.targets +++ b/NetCord.Natives/NetCord.Natives.targets @@ -1,42 +1,20 @@ - + - - true - true - true + + <_NetCordStaticLink Include="libdave;mlspp;bytes;tls_syntax;hpke;libcrypto" + Condition="'%(DirectPInvoke.Identity)' == 'libdave'" /> + <_NetCordStaticLink Include="libsodium" + Condition="'%(DirectPInvoke.Identity)' == 'libsodium'" /> + <_NetCordStaticLink Include="opus" + Condition="'%(DirectPInvoke.Identity)' == 'opus'" /> - true - true - true + - true - - <_NetCordNativesPath>$(NetCordNativesPath)\$(RuntimeIdentifier) - - - - - - - - - - %(NativeFilter.Link) - %(Filename)%(Extension) - PreserveNewest - - - - - - - - + + diff --git a/NetCord.Natives/natives-ports/libdave/portfile.cmake b/NetCord.Natives/natives-ports/libdave/portfile.cmake index 8568d022..a001f80e 100644 --- a/NetCord.Natives/natives-ports/libdave/portfile.cmake +++ b/NetCord.Natives/natives-ports/libdave/portfile.cmake @@ -20,10 +20,8 @@ vcpkg_cmake_build() vcpkg_cmake_install() vcpkg_copy_pdbs() -# file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") - -# file(INSTALL -# "${SOURCE_PATH}/LICENSE" -# DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" -# RENAME LICENSE.txt -# ) \ No newline at end of file +file(INSTALL + "${SOURCE_PATH}/LICENSE" + DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" + RENAME copyright +) diff --git a/README.md b/README.md index b3d29496..cdbb638f 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 binaries dependencies. | ## 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 89a1d414..d7babe22 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](https://www.nuget.org/packages/NetCord.Natives)** | Provides pre-built native binaries dependencies. | ## 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 From f2f238480b2b7070651f89ad8d4b4b0109450043 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Fri, 1 May 2026 05:56:49 +0900 Subject: [PATCH 03/16] feat: native library support and testing - GitHub Actions tag triggers, NuGet publish job - NativesHelper, NativeLibraryVersionAttribute - vcpkg integration, static linking - zstd support - native library tests, import checks - Native AOT test app - NetCordNativesDir assembly metadata --- .github/workflows/build-natives.yml | 41 +- NetCord.Natives/NativesHelper.cs | 20 + NetCord.Natives/NetCord.Natives.csproj | 389 ++++++++++-------- NetCord.Natives/NetCord.Natives.local.targets | 3 +- NetCord.Natives/NetCord.Natives.props | 2 +- NetCord.Natives/NetCord.Natives.targets | 2 + NetCord.Natives/vcpkg.json | 3 +- NetCord.slnx | 1 + Tests/NetCord.Natives.Tests/AssemblyInfo.cs | 3 + .../Assets/NativeAotApp/NativeAotApp.csproj | 24 ++ .../Assets/NativeAotApp/Program.cs | 90 ++++ .../NativesBuildTests.cs | 134 ++++++ .../NetCord.Natives.Tests.csproj | 44 ++ 13 files changed, 562 insertions(+), 194 deletions(-) create mode 100644 NetCord.Natives/NativesHelper.cs create mode 100644 Tests/NetCord.Natives.Tests/AssemblyInfo.cs create mode 100644 Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj create mode 100644 Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs create mode 100644 Tests/NetCord.Natives.Tests/NativesBuildTests.cs create mode 100644 Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index ed3496f2..91d27e9f 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -5,6 +5,10 @@ on: push: paths: - 'NetCord.Natives/**' + - '.github/workflows/build-natives.yml' + tags: + - "[0-9]+.[0-9]+.[0-9]+" + - "[0-9]+.[0-9]+.[0-9]+-*" jobs: build-natives: @@ -57,11 +61,6 @@ jobs: vcpkg-${{ runner.os }}-${{ matrix.rid }}- vcpkg-${{ runner.os }}- - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - name: Resolve vcpkg from runner image shell: pwsh run: | @@ -116,21 +115,6 @@ jobs: path: artifacts merge-multiple: false - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - - name: Resolve native license root - shell: pwsh - run: | - $licenseRoot = Get-ChildItem artifacts -Directory | Sort-Object Name | Select-Object -First 1 - if (-not $licenseRoot) { - throw "No native artifact directories were downloaded." - } - - "NativeLicenseRoot=$($licenseRoot.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - - name: Pack combined nupkg shell: pwsh run: | @@ -141,3 +125,20 @@ jobs: with: name: NetCord.Natives.Package path: artifacts/package/*.nupkg + + publish: + needs: pack-natives + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + steps: + - name: Download nupkg + uses: actions/download-artifact@v4 + with: + name: NetCord.Natives.Package + path: artifacts/package + + - name: Publish Package + env: + KEY: ${{ secrets.NUGET_API_KEY }} + run: | + dotnet nuget push artifacts/package/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/NetCord.Natives/NativesHelper.cs b/NetCord.Natives/NativesHelper.cs new file mode 100644 index 00000000..866a421b --- /dev/null +++ b/NetCord.Natives/NativesHelper.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace NetCord.Natives; + +[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] +public class NativeLibraryVersionAttribute(string name, string version) : Attribute +{ + public string Name { get; } = name; + public string Version { get; } = version; +} + +public static class NativesHelper +{ + public static IEnumerable GetNativeLibraryVersions() + { + return typeof(NativesHelper).Assembly.GetCustomAttributes(); + } +} diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index ef8e1acb..0ea591d8 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -1,175 +1,222 @@ ο»Ώ - - Pre-built native libraries for NetCord, $(Description) - false - - $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..')) - - - - - - - vcpkg\%(Filename)%(Extension) - - - - - - debug - $(MSBuildProjectDirectory)\artifacts - - vcpkg/scripts/buildsystems/msbuild/vcpkg - true - - windows - osx - linux - - x64 - $(Platform) - - bin\natives - $(VcpkgInstalledDir)-static - - $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget) - $(VcpkgInstalledDir)-static\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static - $(BuildNativeOutputPath) - - ClCompile;_CopyNativeLicenses - - - - - - - - - - - - <_NetCordStaticFullPath Include="$([System.IO.Path]::GetFullPath('$(BuildNativeStaticOutputPath)'))" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - <_NativeLicenseSource Include="$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright" Condition="Exists('$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright')"> - $(BuildNativeOutputPath)\licenses\%(AllowedNativesLicenses.Identity)_LICENSE.txt - - - - - - - - - - - - %(Filename)%(Extension) - PreserveNewest - - - - - - - $(PackageId).$(VcpkgOSTarget)-$(VcpkgPlatformTarget) - - - - runtimes\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\native\%(Filename)%(Extension) - - - runtimes-static\$(VcpkgOSTarget)-$(VcpkgPlatformTarget)\%(Filename)%(Extension) - - - - - <_NativeRuntime Include="win-x64"> - runtimes\win-x64\native\ - runtimes-static\win-x64\ - - <_NativeRuntime Include="win-arm64"> - runtimes\win-arm64\native\ - runtimes-static\win-arm64\ - - <_NativeRuntime Include="osx-x64"> - runtimes\osx-x64\native\ - runtimes-static\osx-x64\ - - <_NativeRuntime Include="osx-arm64"> - runtimes\osx-arm64\native\ - runtimes-static\osx-arm64\ - - <_NativeRuntime Include="linux-x64"> - runtimes\linux-x64\native\ - runtimes-static\linux-x64\ - - <_NativeRuntime Include="linux-arm64"> - runtimes\linux-arm64\native\ - runtimes-static\linux-arm64\ - - - - %(_NativeRuntime.PackageRuntimePath)%(Filename)%(Extension) - - - %(_NativeRuntime.PackageStaticPath)%(Filename)%(Extension) - - - - - - true - %(NativesBuilt.TargetPath) - - - - true - licenses\ - - - <_BuildFiles Include="$(MSBuildProjectName).props;$(MSBuildProjectName).targets"> - true - - - - build\$(PackageId)%(Extension) - - - buildTransitive\$(PackageId)%(Extension) - - - - - - - - + + Pre-built native libraries for NetCord, $(Description) + false + + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..')) + + + + + + + vcpkg\%(Filename)%(Extension) + + + + + + debug + + vcpkg/scripts/buildsystems/msbuild/vcpkg + true + + windows + osx + linux + + $(VcpkgOSTarget) + win + + x64 + $(Platform) + + bin + + $(NativeArtifactsRoot)\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\natives + $(VcpkgInstalledDir)-static + + $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget) + $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static + + <_BuildNativeStaticOutputPath>$(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static + <_VcpkgStatusFile>$(VcpkgInstalledDir)\vcpkg\status + + + + + + + + + + + + + + <_NetCordStaticFullPath Include="$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(_BuildNativeStaticOutputPath)'))" /> + + + + + + + + + + + + + + + + + + + + + + + + <_NativeLicenseSource Include="$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright" + Condition="Exists('$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright')"> + $(BuildNativeOutputPath)\licenses\%(AllowedNativesLicenses.Identity)_LICENSE.txt + + + + + + + + + + + + + + + + @(StatusLines, ' ') + + + + + + + $([System.Text.RegularExpressions.Regex]::Match('$(StatusText)', 'Package: %(Identity)\n(?:.*\n)*?Version: (.*?)\n').Groups[1].Value) + + + + + + + <_Parameter1>%(PackageWithVersion.Identity) + <_Parameter2>%(PackageWithVersion.Version) + + + + + + + + + + + + + %(Filename)%(Extension) + PreserveNewest + false + + + + + + + + $(PackageId).$(VcpkgBuildOS)-$(VcpkgPlatformTarget) + + + + + runtimes\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\native\ + + + staticlibs\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\ + + + + + <_BuiltTriplets Include="x64-windows"> + win-x64 + x64-windows\bin\%(AllowedNativeLibrary.Identity) + x64-windows-static\lib\%(AllowedNativeLibrary.Identity) + + <_BuiltTriplets Include="arm64-windows"> + win-arm64 + arm64-windows\bin\%(AllowedNativeLibrary.Identity) + arm64-windows-static\lib\%(AllowedNativeLibrary.Identity) + + <_BuiltTriplets Include="x64-linux"> + linux-x64 + x64-linux\bin\%(AllowedNativeLibrary.Identity) + x64-linux-static\lib\%(AllowedNativeLibrary.Identity) + + <_BuiltTriplets Include="arm64-linux"> + linux-arm64 + arm64-linux\bin\%(AllowedNativeLibrary.Identity) + arm64-linux-static\lib\%(AllowedNativeLibrary.Identity) + + <_BuiltTriplets Include="x64-osx"> + osx-x64 + x64-osx\bin\%(AllowedNativeLibrary.Identity) + x64-osx-static\lib\%(AllowedNativeLibrary.Identity) + + <_BuiltTriplets Include="arm64-osx"> + osx-arm64 + arm64-osx\bin\%(AllowedNativeLibrary.Identity) + arm64-osx-static\lib\%(AllowedNativeLibrary.Identity) + + + + runtimes\%(_BuiltTriplets.RuntimeId)\native\ + + + staticlibs\%(_BuiltTriplets.RuntimeId)\ + + + + + + true + + + + true + licenses\ + + + <_BuildFiles Include="$(MSBuildProjectName).props;$(MSBuildProjectName).targets"> + true + + + + build\$(PackageId)%(Extension) + + + buildTransitive\$(PackageId)%(Extension) + + + + + + + + diff --git a/NetCord.Natives/NetCord.Natives.local.targets b/NetCord.Natives/NetCord.Natives.local.targets index 1c79590d..7a542e0e 100644 --- a/NetCord.Natives/NetCord.Natives.local.targets +++ b/NetCord.Natives/NetCord.Natives.local.targets @@ -4,7 +4,8 @@ - + diff --git a/NetCord.Natives/NetCord.Natives.props b/NetCord.Natives/NetCord.Natives.props index 021708eb..10bbd708 100644 --- a/NetCord.Natives/NetCord.Natives.props +++ b/NetCord.Natives/NetCord.Natives.props @@ -1,7 +1,7 @@ - $(MSBuildThisFileDirectory)..\runtimes-static\$(RuntimeIdentifier) + $(MSBuildThisFileDirectory)..\staticlibs\$(RuntimeIdentifier) diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets index 16d61ae6..a9ab04c5 100644 --- a/NetCord.Natives/NetCord.Natives.targets +++ b/NetCord.Natives/NetCord.Natives.targets @@ -9,6 +9,8 @@ Condition="'%(DirectPInvoke.Identity)' == 'libsodium'" /> <_NetCordStaticLink Include="opus" Condition="'%(DirectPInvoke.Identity)' == 'opus'" /> + <_NetCordStaticLink Include="zstd" + Condition="'%(DirectPInvoke.Identity)' == 'zstd'" /> diff --git a/NetCord.Natives/vcpkg.json b/NetCord.Natives/vcpkg.json index 426671ba..1712ed4f 100644 --- a/NetCord.Natives/vcpkg.json +++ b/NetCord.Natives/vcpkg.json @@ -2,7 +2,8 @@ "dependencies": [ "libdave", "opus", - "libsodium" + "libsodium", + "zstd" ], "vcpkg-configuration": { "overlay-ports": [ diff --git a/NetCord.slnx b/NetCord.slnx index fd20607e..08ac717d 100644 --- a/NetCord.slnx +++ b/NetCord.slnx @@ -84,6 +84,7 @@ + diff --git a/Tests/NetCord.Natives.Tests/AssemblyInfo.cs b/Tests/NetCord.Natives.Tests/AssemblyInfo.cs new file mode 100644 index 00000000..ae411c7a --- /dev/null +++ b/Tests/NetCord.Natives.Tests/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj new file mode 100644 index 00000000..05c22e53 --- /dev/null +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj @@ -0,0 +1,24 @@ + + + + Exe + net10.0 + enable + enable + + true + true + + + + + + + + + + + + + + diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs new file mode 100644 index 00000000..a6440685 --- /dev/null +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs @@ -0,0 +1,90 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +internal static partial class NativeProbes +{ + [LibraryImport("libdave", EntryPoint = "daveMaxSupportedProtocolVersion")] + internal static partial uint DaveMaxSupportedProtocolVersion(); + + [LibraryImport("libsodium", EntryPoint = "sodium_init")] + internal static partial int SodiumInit(); + + [LibraryImport("opus", EntryPoint = "opus_get_version_string")] + internal static partial nint OpusGetVersionString(); + + [LibraryImport("libzstd", EntryPoint = "ZSTD_versionNumber")] + internal static partial uint ZstdVersionNumber(); +} + +internal static class Program +{ + private static void Main() + { + Console.WriteLine("NetCord native ahead of time publish app."); + + Console.WriteLine($"Dave Max Supported Protocol Version: {NativeProbes.DaveMaxSupportedProtocolVersion()}"); + Console.WriteLine($"Sodium Init: {NativeProbes.SodiumInit()}"); + Console.WriteLine($"Opus Version String: {Marshal.PtrToStringAnsi(NativeProbes.OpusGetVersionString())}"); + Console.WriteLine($"Zstd Version Number: {NativeProbes.ZstdVersionNumber()}"); + + var cwd = Path.GetFullPath(Directory.GetCurrentDirectory()); + Console.WriteLine($"Current working directory: {cwd}"); + + string[] libraries = new[] { "libdave", "libsodium", "opus", "libzstd" }; + var process = Process.GetCurrentProcess(); + var modules = process.Modules; + + bool allUnderCwd = true; + + foreach (var lib in libraries) + { + ProcessModule found = null; + foreach (ProcessModule m in modules) + { + if (!string.IsNullOrEmpty(m.FileName) && m.FileName.IndexOf(lib, StringComparison.OrdinalIgnoreCase) >= 0) + { + found = m; + break; + } + if (!string.IsNullOrEmpty(m.ModuleName) && m.ModuleName.IndexOf(lib, StringComparison.OrdinalIgnoreCase) >= 0) + { + found = m; + break; + } + } + + if (found == null) + { + Console.WriteLine($"Library '{lib}' not found among loaded modules."); + allUnderCwd = false; + continue; + } + + Console.WriteLine($"{lib} loaded from: {found.FileName}"); + if (!IsUnderDirectory(found.FileName, cwd)) + { + Console.WriteLine($"Library '{lib}' is not under current working directory."); + allUnderCwd = false; + } + } + + Environment.Exit(allUnderCwd ? 0 : 1); + } + + private static bool IsUnderDirectory(string path, string directory) + { + try + { + var fullPath = Path.GetFullPath(path); + var fullDir = Path.GetFullPath(directory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; + var comparison = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; + return fullPath.StartsWith(fullDir, comparison); + } + catch + { + return false; + } + } +} diff --git a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs new file mode 100644 index 00000000..b47e24bb --- /dev/null +++ b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs @@ -0,0 +1,134 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace NetCord.Natives.Tests; + +[TestClass] +public class NativesBuildTests +{ + // MSTest automatically injects this property + public TestContext TestContext { get; set; } + + [TestMethod] + [DataRow("libdave")] + [DataRow("libsodium")] + [DataRow("opus")] + [DataRow("zstd")] + public void NativesLoaded(string libName) + { + try + { + NativeLibrary.Load(libName); + } + catch (Exception ex) + { + Assert.Fail($"Failed to load library '{libName}': {ex}"); + } + } + + [TestMethod] + [DataRow("libdave", "NetCord.Gateway.Voice.Dave")] + [DataRow("libsodium", "NetCord.Gateway.Voice.Encryption.XChaCha20Poly1305")] + [DataRow("opus", "NetCord.Gateway.Voice.Opus")] + [DataRow("zstd", "NetCord.Gateway.Compression.Zstandard")] + public void AllLibraryImportsExistInBinary(string libName, string className) + { + IntPtr libHandle = IntPtr.Zero; + + try + { + var assembly = typeof(NetCord.Application).Assembly; + var typeWithImports = assembly.GetType(className, true); + + libHandle = NativeLibrary.Load(libName); + + var missingExports = new List(); + + // Reflect over methods with [LibraryImport] + var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + .Select(m => new { + MethodName = m.Name, + Attr = m.GetCustomAttribute() + }) + .Where(x => x.Attr != null); + Assert.IsNotEmpty(methods, $"No methods with [LibraryImport] found in '{className}'."); + + foreach (var item in methods) + { + // Use EntryPoint if defined, otherwise fallback to Method Name + string exportName = item.Attr!.EntryPoint ?? item.MethodName; + + if (!NativeLibrary.TryGetExport(libHandle, exportName, out _)) + { + missingExports.Add(exportName); + } + } + Assert.IsEmpty(missingExports, $"The following entry points were not found in '{libName}': {string.Join(", ", missingExports)}"); + } + catch (Exception ex) + { + Assert.Fail($"An error occurred while verifying imports for '{libName}': {ex}"); + } + finally + { + NativeLibrary.Free(libHandle); + } + } + + [TestMethod] + [DataRow("libdave;libsodium;opus;zstd")] + public void NativeAotStaticLinking(string libName) + { + try + { + // get NetCordNativesDir from AssemblyMetadata attribute + var assembly = typeof(NativesBuildTests).Assembly; + var nativesDir = assembly.GetCustomAttribute()?.Value; + Assert.IsNotNull(nativesDir, "NetCordNativesDir metadata attribute is not defined."); + + // build asset NativeAotApp with Native AoT enabled + var buildProcess = new System.Diagnostics.Process(); + buildProcess.StartInfo.FileName = "dotnet"; + buildProcess.StartInfo.ArgumentList.Add("publish"); + buildProcess.StartInfo.ArgumentList.Add("-p:Configuration=Release"); + buildProcess.StartInfo.ArgumentList.Add("-p:RuntimeIdentifier=" + RuntimeInformation.RuntimeIdentifier); + buildProcess.StartInfo.ArgumentList.Add($"-p:NetCordNativesDir={nativesDir}"); + buildProcess.StartInfo.ArgumentList.Add($"-p:NetCordDirectPInvoke=\"{libName}\""); + + TestContext.WriteLine($"Building Native AoT app: 'dotnet {buildProcess.StartInfo.ArgumentList.Aggregate((a, b) => $"{a} {b}")}'"); + + buildProcess.StartInfo.WorkingDirectory = Path.Combine(AppContext.BaseDirectory, "Assets", "NativeAotApp"); + buildProcess.StartInfo.RedirectStandardOutput = true; + buildProcess.StartInfo.RedirectStandardError = true; + buildProcess.Start(); + buildProcess.WaitForExit(); + + TestContext.WriteLine($"Build Output of AoT app for '{libName}': {buildProcess.StandardOutput.ReadToEnd()}"); + + Assert.AreEqual(0, buildProcess.ExitCode, + $"Native AoT build failed for '{libName}'. Output: {buildProcess.StandardError.ReadToEnd()}"); + + // check that the library is running without errors, which indicates that it was statically linked successfully + var aotProcess = new System.Diagnostics.Process(); + aotProcess.StartInfo.FileName = Path.Combine(AppContext.BaseDirectory, "Assets", "NativeAotApp", + "bin", "release", RuntimeInformation.RuntimeIdentifier, "publish", "NativeAotApp.exe"); + + TestContext.WriteLine($"Running Native AoT app: '{aotProcess.StartInfo.FileName}'"); + + aotProcess.StartInfo.RedirectStandardOutput = true; + aotProcess.StartInfo.RedirectStandardError = true; + aotProcess.Start(); + aotProcess.WaitForExit(); + + TestContext.WriteLine($"Output of AoT app for '{libName}': {aotProcess.StandardOutput.ReadToEnd()}"); + + Assert.AreEqual(0, aotProcess.ExitCode, + $"Native AoT app failed to run for '{libName}'. Output: {aotProcess.StandardError.ReadToEnd()}"); + } + catch (Exception ex) + { + Assert.Fail($"Failed to statically link '{libName}' for Native Ahead-of-Time (AoT) compilation: {ex}"); + } + } +} diff --git a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj new file mode 100644 index 00000000..9ddd5a5b --- /dev/null +++ b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj @@ -0,0 +1,44 @@ + + + + net10.0 + enable + enable + + false + true + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + ..\..\NetCord.Natives\ + + + + + + <_Parameter1>NetCordNativesDir + <_Parameter2>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(NetCordNativesDir)')) + + + + + + + + From a805dd6dd61b6be49bfcb66e85e04cf76d233667 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Tue, 5 May 2026 03:00:19 +0900 Subject: [PATCH 04/16] * Refactor NetCord.Natives.csproj for improved build configuration * Add MSVC builtin add overflow patch for libdave * Add vcpkg-non-windows.targets for cross-platform support * Update libdave and mlspp portfiles with build fixes * Update build-natives workflow and vcpkg.json versions * Fix vcpkg dependency resolution for multi-platform builds --- .github/workflows/build-natives.yml | 10 +- NetCord.Natives/NetCord.Natives.csproj | 186 +++++++++--------- .../fix-msvc-builtin-add-overflow.patch | 24 +++ .../natives-ports/libdave/portfile.cmake | 5 + .../natives-ports/mlspp/portfile.cmake | 4 + NetCord.Natives/vcpkg-non-windows.targets | 48 +++++ NetCord.Natives/vcpkg.json | 9 +- 7 files changed, 187 insertions(+), 99 deletions(-) create mode 100644 NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch create mode 100644 NetCord.Natives/vcpkg-non-windows.targets diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index 91d27e9f..26e8a3ba 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -71,7 +71,11 @@ jobs: } if (-not (Test-Path $vcpkgRoot)) { - throw "vcpkg installation root not found." + # Bootstrap vcpkg + if ($IsWindows) { + & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics + } else { + & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics } "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 @@ -85,7 +89,7 @@ jobs: - name: Build native outputs for ${{ matrix.rid }} shell: pwsh run: | - dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} - name: List artifacts shell: pwsh @@ -118,7 +122,7 @@ jobs: - name: Pack combined nupkg shell: pwsh run: | - dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:NativeArtifactsRoot=$env:NativeArtifactsRoot -p:NativeLicenseRoot=$env:NativeLicenseRoot -o artifacts/package + dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:NativeArtifactsRoot=$env:NativeArtifactsRoot -p:NativeLicenseRoot=$env:NativeLicenseRoot -o artifacts/package - name: Upload nupkg uses: actions/upload-artifact@v4 diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 0ea591d8..67dbfe4f 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -19,7 +19,12 @@ debug - vcpkg/scripts/buildsystems/msbuild/vcpkg + bin + + $(VCPKG_ROOT) + $(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg + + Release true windows @@ -28,71 +33,104 @@ $(VcpkgOSTarget) win - + + + false + x64 $(Platform) - bin - - $(NativeArtifactsRoot)\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\natives + $(VcpkgArtifactsRoot)\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\natives + $(VcpkgInstalledDirBase) $(VcpkgInstalledDir)-static - $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget) - $(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static - - <_BuildNativeStaticOutputPath>$(VcpkgInstalledDir)\$(VcpkgPlatformTarget)-$(VcpkgOSTarget)-static + $(VcpkgInstalledDirBase)-static\$(VcpkgPlatformTarget)-$(VcpkgOSTarget) + $(VcpkgOutputPath_Static)-static <_VcpkgStatusFile>$(VcpkgInstalledDir)\vcpkg\status - - - - + + + + + - + + + <_VcpkgRelatedFile Include="native-ports\**" /> - + - <_NetCordStaticFullPath Include="$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(_BuildNativeStaticOutputPath)'))" /> + <_StaticFullPath Include="$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(VcpkgOutputPath_Static)'))" /> - + + + + + + + $(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="osx-%(_LibArchs.Identity)"> + %(_LibArchs.Identity)-osx-dynamic\lib\lib%(_LibArchs.LibName) + %(_LibArchs.Identity)-osx\lib\lib%(_LibArchs.LibName) + dylib + + <_BuiltRid Remove="%(Identity)" Condition="'$(CI)' != 'true' and '%(Identity)' != '$(VcpkgBuildOS)-$(VcpkgPlatformTarget)'" /> + - - + + + - - - <_NativeLicenseSource Include="$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright" - Condition="Exists('$(BuildNativeOutputPath)\share\%(AllowedNativesLicenses.Identity)\copyright')"> - $(BuildNativeOutputPath)\licenses\%(AllowedNativesLicenses.Identity)_LICENSE.txt + Properties="VcpkgUseStatic=true;GeneratePackageOnBuild=false" + Condition="'$(VcpkgUseStatic)' != 'true'" /> + + + <_NativeLicenseSource Include="$(VcpkgOutputPath)\share\%(NativeLibLic.Identity)\copyright" + Condition="Exists('$(VcpkgOutputPath)\share\%(NativeLibLic.Identity)\copyright')"> + $(VcpkgOutputPath)\licenses\%(NativeLibLic.Identity)_LICENSE.txt + SkipUnchangedFiles="true" Condition="'$(VcpkgUseStatic)' != 'true'" /> - + @@ -106,27 +144,27 @@ - + <_VcpkgPkg Include="@(NativeLibLic)"> $([System.Text.RegularExpressions.Regex]::Match('$(StatusText)', 'Package: %(Identity)\n(?:.*\n)*?Version: (.*?)\n').Groups[1].Value) - + - - <_Parameter1>%(PackageWithVersion.Identity) - <_Parameter2>%(PackageWithVersion.Version) + + <_Parameter1>%(_VcpkgPkg.Identity) + <_Parameter2>%(_VcpkgPkg.Version) - + - + - + %(Filename)%(Extension) @@ -136,67 +174,25 @@ - + $(PackageId).$(VcpkgBuildOS)-$(VcpkgPlatformTarget) - - - runtimes\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\native\ - - - staticlibs\$(VcpkgBuildOS)-$(VcpkgPlatformTarget)\ - - - - - <_BuiltTriplets Include="x64-windows"> - win-x64 - x64-windows\bin\%(AllowedNativeLibrary.Identity) - x64-windows-static\lib\%(AllowedNativeLibrary.Identity) - - <_BuiltTriplets Include="arm64-windows"> - win-arm64 - arm64-windows\bin\%(AllowedNativeLibrary.Identity) - arm64-windows-static\lib\%(AllowedNativeLibrary.Identity) - - <_BuiltTriplets Include="x64-linux"> - linux-x64 - x64-linux\bin\%(AllowedNativeLibrary.Identity) - x64-linux-static\lib\%(AllowedNativeLibrary.Identity) - - <_BuiltTriplets Include="arm64-linux"> - linux-arm64 - arm64-linux\bin\%(AllowedNativeLibrary.Identity) - arm64-linux-static\lib\%(AllowedNativeLibrary.Identity) - - <_BuiltTriplets Include="x64-osx"> - osx-x64 - x64-osx\bin\%(AllowedNativeLibrary.Identity) - x64-osx-static\lib\%(AllowedNativeLibrary.Identity) - - <_BuiltTriplets Include="arm64-osx"> - osx-arm64 - arm64-osx\bin\%(AllowedNativeLibrary.Identity) - arm64-osx-static\lib\%(AllowedNativeLibrary.Identity) - - - - runtimes\%(_BuiltTriplets.RuntimeId)\native\ + + + runtimes\%(_BuiltRid.Identity)\native\ - - staticlibs\%(_BuiltTriplets.RuntimeId)\ + + staticlibs\%(_BuiltRid.Identity)\ - - - + true - + true licenses\ diff --git a/NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch b/NetCord.Natives/natives-ports/libdave/fix-msvc-builtin-add-overflow.patch new file mode 100644 index 00000000..f6d3360a --- /dev/null +++ b/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/NetCord.Natives/natives-ports/libdave/portfile.cmake b/NetCord.Natives/natives-ports/libdave/portfile.cmake index a001f80e..4f7517e7 100644 --- a/NetCord.Natives/natives-ports/libdave/portfile.cmake +++ b/NetCord.Natives/natives-ports/libdave/portfile.cmake @@ -4,6 +4,7 @@ vcpkg_from_github( REF "${VERSION}" SHA512 78b4e5b8ddc6397775d403465e0da770ec7905d7913546b3aec161baf4478443e554f0ae7bd012af8bfd308639be2601d46da22c02aff2b756ff91878f1fc843 HEAD_REF main + PATCHES fix-msvc-builtin-add-overflow.patch ) vcpkg_cmake_configure( @@ -25,3 +26,7 @@ file(INSTALL 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/NetCord.Natives/natives-ports/mlspp/portfile.cmake b/NetCord.Natives/natives-ports/mlspp/portfile.cmake index 66dd943c..2ca219e3 100644 --- a/NetCord.Natives/natives-ports/mlspp/portfile.cmake +++ b/NetCord.Natives/natives-ports/mlspp/portfile.cmake @@ -27,3 +27,7 @@ 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/NetCord.Natives/vcpkg-non-windows.targets b/NetCord.Natives/vcpkg-non-windows.targets new file mode 100644 index 00000000..134e697a --- /dev/null +++ b/NetCord.Natives/vcpkg-non-windows.targets @@ -0,0 +1,48 @@ + + + + <_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgManifestFileLocation)"/> + <_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgConfigurationFileLocation)" + Condition="Exists('$(_ZVcpkgConfigurationFileLocation)')"/> + + + + + + + <_ZVcpkgTLogFileLocation>$(TLogLocation)VcpkgInstallManifest$(VcpkgTriplet).$(_ZVcpkgHostTripletSuffix)read.1u.tlog + + <_ZVcpkgExecutable>$(_ZVcpkgRoot)vcpkg + + + + + + + + + + + + + + + + + + + diff --git a/NetCord.Natives/vcpkg.json b/NetCord.Natives/vcpkg.json index 1712ed4f..a3af5a40 100644 --- a/NetCord.Natives/vcpkg.json +++ b/NetCord.Natives/vcpkg.json @@ -9,5 +9,12 @@ "overlay-ports": [ "natives-ports" ] - } + }, + "builtin-baseline": "d07689ef165f033de5c0710e4f67c193a85373e1", + "overrides": [ + { + "name": "openssl", + "version": "3.0.7" + } + ] } From 5c2f7f039c42a548608eb5515b94c2d8bd8cbed5 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Tue, 5 May 2026 21:18:49 +0900 Subject: [PATCH 05/16] * Refactor native library handling and packaging * Add dynamic library exclusion for AOT builds * Add NativeAotApp test project --- NetCord.Natives/NetCord.Natives.csproj | 32 +++++++++---------- NetCord.Natives/NetCord.Natives.local.targets | 12 +++++-- NetCord.Natives/NetCord.Natives.props | 9 ++++++ NetCord.Natives/NetCord.Natives.targets | 28 ++++++++++++++-- NetCord.slnx | 1 + .../Assets/NativeAotApp/NativeAotApp.csproj | 20 ++++++------ .../Assets/NativeAotApp/Program.cs | 6 ++-- 7 files changed, 75 insertions(+), 33 deletions(-) diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 67dbfe4f..216d209f 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -117,16 +117,6 @@ - - - <_NativeLicenseSource Include="$(VcpkgOutputPath)\share\%(NativeLibLic.Identity)\copyright" - Condition="Exists('$(VcpkgOutputPath)\share\%(NativeLibLic.Identity)\copyright')"> - $(VcpkgOutputPath)\licenses\%(NativeLibLic.Identity)_LICENSE.txt - - - - - + - - + <_CopyOutput Include="%(NativesRuntime.FullPath)" Condition="Exists('%(NativesRuntime.Identity)')"> %(Filename)%(Extension) PreserveNewest - false - + + + + <_NativeLicenseSource Include="$(VcpkgOutputPath_Static)\share\%(NativeLibLic.Identity)\copyright" + Condition="Exists('$(VcpkgOutputPath_Static)\share\%(NativeLibLic.Identity)\copyright')"> + $(VcpkgOutputPath_Static)\licenses\%(NativeLibLic.Identity)_LICENSE.txt + + + + + $(PackageId).$(VcpkgBuildOS)-$(VcpkgPlatformTarget) @@ -192,7 +192,7 @@ true - + true licenses\ diff --git a/NetCord.Natives/NetCord.Natives.local.targets b/NetCord.Natives/NetCord.Natives.local.targets index 7a542e0e..3f730cc0 100644 --- a/NetCord.Natives/NetCord.Natives.local.targets +++ b/NetCord.Natives/NetCord.Natives.local.targets @@ -5,12 +5,20 @@ + Targets="GetStaticBuildDir" + Properties="CI=false"> + + + + - @(_NetCordStaticDir->'%(Identity)')\lib + %(_NetCordStaticDir.Identity)\lib + $([System.IO.Path]::GetDirectoryName('%(_NetCordRuntimesDir.FullPath)')) diff --git a/NetCord.Natives/NetCord.Natives.props b/NetCord.Natives/NetCord.Natives.props index 10bbd708..c1b6ee94 100644 --- a/NetCord.Natives/NetCord.Natives.props +++ b/NetCord.Natives/NetCord.Natives.props @@ -1,6 +1,15 @@ + + + + $(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier) $(MSBuildThisFileDirectory)..\staticlibs\$(RuntimeIdentifier) diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets index a9ab04c5..93d835ee 100644 --- a/NetCord.Natives/NetCord.Natives.targets +++ b/NetCord.Natives/NetCord.Natives.targets @@ -12,11 +12,35 @@ <_NetCordStaticLink Include="zstd" Condition="'%(DirectPInvoke.Identity)' == 'zstd'" /> - + + - + + + + + <_NetCordExcluded Include="$(NetCordExcludeNatives)" + Condition="'$(NetCordExcludeNatives)' != ''" /> + <_NetCordExcluded Include="libcrypto" + Condition="$(NetCordExcludeNatives.Contains('libdave'))" /> + + <_NetCordExcluded Include="@(_NetCordStaticLink)" + Condition="'$(PublishAot)' == 'true' and '%(_NetCordStaticLink.Identity)' != ''"/> + + <_RunExclude Include="$(NetCordNativesRuntimesDir)\**\native\%(_NetCordExcluded.Identity)*.*" + Condition="'@(_NetCordExcluded.Identity)' != ''" /> + <_RunExclude Include="$(NetCordNativesRuntimesDir)\**\native\lib%(_NetCordExcluded.Identity)*.*" + Condition="'@(_NetCordExcluded.Identity)' != ''" /> + + + + + + diff --git a/NetCord.slnx b/NetCord.slnx index 08ac717d..2338dbc5 100644 --- a/NetCord.slnx +++ b/NetCord.slnx @@ -85,6 +85,7 @@ + diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj index 05c22e53..8209957b 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj @@ -1,4 +1,4 @@ - +ο»Ώ Exe @@ -8,17 +8,17 @@ true true + true + false + + ..\..\..\..\NetCord.Natives - - - - - - + + + - - - + + diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs index a6440685..111e3a69 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs @@ -14,7 +14,7 @@ internal static partial class NativeProbes [LibraryImport("opus", EntryPoint = "opus_get_version_string")] internal static partial nint OpusGetVersionString(); - [LibraryImport("libzstd", EntryPoint = "ZSTD_versionNumber")] + [LibraryImport("zstd", EntryPoint = "ZSTD_versionNumber")] internal static partial uint ZstdVersionNumber(); } @@ -32,7 +32,7 @@ private static void Main() var cwd = Path.GetFullPath(Directory.GetCurrentDirectory()); Console.WriteLine($"Current working directory: {cwd}"); - string[] libraries = new[] { "libdave", "libsodium", "opus", "libzstd" }; + string[] libraries = new[] { "libdave", "libsodium", "opus", "zstd" }; var process = Process.GetCurrentProcess(); var modules = process.Modules; @@ -40,7 +40,7 @@ private static void Main() foreach (var lib in libraries) { - ProcessModule found = null; + ProcessModule? found = null; foreach (ProcessModule m in modules) { if (!string.IsNullOrEmpty(m.FileName) && m.FileName.IndexOf(lib, StringComparison.OrdinalIgnoreCase) >= 0) From a5e9a4c17a72aa629c4ef40386810c092ea173e0 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Wed, 6 May 2026 03:58:37 +0900 Subject: [PATCH 06/16] CI finished & fix typos & guarding --- .github/workflows/build-natives.yml | 119 ++++++++++++++++++++----- NetCord.Natives/NetCord.Natives.csproj | 4 +- 2 files changed, 99 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index 26e8a3ba..27e5fd3e 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -48,15 +48,19 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6.0.2 - name: Cache vcpkg installs - uses: actions/cache@v4 + uses: actions/cache@v5.0.5 with: path: | .vcpkg-cache .vcpkg-downloads - key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json') }} + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}- + ${{ hashFiles( + 'NetCord.Natives/vcpkg.json', + 'NetCord.Natives/natives-ports/**' + ) }} restore-keys: | vcpkg-${{ runner.os }}-${{ matrix.rid }}- vcpkg-${{ runner.os }}- @@ -64,68 +68,139 @@ jobs: - name: Resolve vcpkg from runner image shell: pwsh run: | + # Ensure vcpkg cache and downloads directories exist + New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null + New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null + $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT if (-not $vcpkgRoot) { $vcpkgCommand = Get-Command vcpkg -ErrorAction Stop $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source } - if (-not (Test-Path $vcpkgRoot)) { - # Bootstrap vcpkg - if ($IsWindows) { - & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics - } else { - & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics + if (Test-Path $vcpkgRoot) { + # Bootstrap vcpkg + if ($IsWindows) { + & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics + } else { + & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics + } } "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - "VcpkgMsbuildPath=$vcpkgRoot/scripts/buildsystems/msbuild/vcpkg" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Install native build tools (macOS) + if: runner.os == 'macOS' + shell: bash + run: | + brew update + brew install autoconf automake libtool pkg-config + + - name: Install ARM64 cross-compiler (linux-arm64) + if: matrix.rid == 'linux-arm64' + shell: bash + run: | + sudo apt-get update + sudo apt-get install -yq gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross - name: Restore shell: pwsh run: | - dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} - name: Build native outputs for ${{ matrix.rid }} shell: pwsh run: | - dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} - - name: List artifacts + - name: List built for ${{ matrix.rid }} shell: pwsh run: | - Get-ChildItem -Recurse NetCord.Natives/bin | Select-Object FullName + $rid = '${{ matrix.rid }}' + $tripletBase = '${{ matrix.vcpkg-platform-target }}-${{ matrix.vcpkg-os-target }}' + $suffix = if ($IsWindows) { 'static' } else { 'dynamic' } + $triplets = @("$tripletBase", "$tripletBase-$suffix") + + foreach ($variant in @('natives','natives-static')) { + foreach ($triplet in @($triplets)) { + foreach ($folder in @('bin','lib')) { + $path = "NetCord.Natives/bin/$rid/$variant/$triplet/$folder" + if (Test-Path $path) { + Write-Host "Contents of: $path" + Get-ChildItem -Path $path -Recurse -Force | Select-Object FullName, Mode, Length, LastWriteTime + } else { + Write-Host "[Info]Not found: $path" + } + } + } + } - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7.0.1 with: name: ${{ matrix.rid }} - path: NetCord.Natives/bin + path: NetCord.Natives/bin/${{ matrix.rid }} pack-natives: needs: build-natives runs-on: ubuntu-latest env: CI: true - NativeArtifactsRoot: ${{ github.workspace }}/artifacts + VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite + VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads + VcpkgArtifactsRoot: ${{ github.workspace }}/artifacts steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6.0.2 - name: Download native artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8.0.1 with: path: artifacts merge-multiple: false + - name: Resolve vcpkg from runner image + shell: pwsh + run: | + # Ensure vcpkg cache and downloads directories exist + New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null + New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null + + $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT + if (-not $vcpkgRoot) { + $vcpkgCommand = Get-Command vcpkg -ErrorAction Stop + $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source + } + + if (Test-Path $vcpkgRoot) { + # Bootstrap vcpkg + if ($IsWindows) { + & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics + } else { + & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics + } + } + + "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Restore (required for pack) + shell: pwsh + run: | + dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgEnabled=false + + - name: Build cross-platform .NET (required for pack) + shell: pwsh + run: | + dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgEnabled=false + - name: Pack combined nupkg shell: pwsh run: | - dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgMsbuildPath=$env:VcpkgMsbuildPath -p:NativeArtifactsRoot=$env:NativeArtifactsRoot -p:NativeLicenseRoot=$env:NativeLicenseRoot -o artifacts/package + dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgArtifactsRoot=$env:VcpkgArtifactsRoot -o $env:VcpkgArtifactsRoot/package - name: Upload nupkg - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7.0.1 with: name: NetCord.Natives.Package path: artifacts/package/*.nupkg @@ -136,7 +211,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download nupkg - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8.0.1 with: name: NetCord.Natives.Package path: artifacts/package diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 216d209f..621f5065 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -55,7 +55,7 @@ - + @@ -174,7 +174,7 @@ + SkipUnchangedFiles="true" Condition="'@(_NativeLicenseSource)' != ''" /> $(PackageId).$(VcpkgBuildOS)-$(VcpkgPlatformTarget) From 6d485fbd324b3cfe3e0cc126d8fa81e348ba2c53 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Wed, 6 May 2026 04:10:51 +0900 Subject: [PATCH 07/16] solution build fix --- .../Assets/NativeAotApp/NativeAotApp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj index 8209957b..2eade721 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj @@ -11,7 +11,7 @@ true false - ..\..\..\..\NetCord.Natives + ..\..\..\..\NetCord.Natives From f9cfc3f3a5eb808974047f942b70e51e001f36e3 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Wed, 6 May 2026 06:36:19 +0900 Subject: [PATCH 08/16] separate solution for natives * natives conditionals fix * fix nativeaot test structure * add natives tests to build workflow --- .github/workflows/build-natives.yml | 9 ++- .github/workflows/build.yml | 6 +- NetCord.Natives.slnx | 7 +++ NetCord.Natives/NetCord.Natives.csproj | 12 ++-- NetCord.Natives/NetCord.Natives.local.targets | 5 +- NetCord.Natives/NetCord.Natives.targets | 4 +- NetCord.slnx | 4 +- .../Assets/NativeAotApp/NativeAotApp.csproj | 1 + .../Assets/NativeAotApp/Program.cs | 60 +------------------ .../NativesBuildTests.cs | 31 ++++++++-- .../NetCord.Natives.Tests.csproj | 8 +++ 11 files changed, 67 insertions(+), 80 deletions(-) create mode 100644 NetCord.Natives.slnx diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index 27e5fd3e..c56bd99c 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -1,4 +1,4 @@ -name: Build NetCord.Natives +name: Build, Test, and Package NetCord.Natives on: workflow_dispatch: {} @@ -11,7 +11,7 @@ on: - "[0-9]+.[0-9]+.[0-9]+-*" jobs: - build-natives: + build-test-natives: runs-on: ${{ matrix.runs-on }} env: CI: true @@ -113,6 +113,11 @@ jobs: run: | dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + - name: Test native outputs for ${{ matrix.rid }} + shell: pwsh + run: | + dotnet test NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -c Release -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} --verbosity normal + - name: List built for ${{ matrix.rid }} shell: pwsh run: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 40c35ec0..89f48496 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,11 +38,13 @@ jobs: - name: Build shell: *dev-shell - run: dotnet build -c Release --no-restore --warnaserror + run: | + dotnet build NetCord.slnx -c Release --no-restore --warnaserror + dotnet build NetCord.Natives.slnx -c Release --no-restore --warnaserror -p:VcpkgRoot=$VCPKG_INSTALLATION_ROOT -p:VcpkgEnabled=false - 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 diff --git a/NetCord.Natives.slnx b/NetCord.Natives.slnx new file mode 100644 index 00000000..1f71c569 --- /dev/null +++ b/NetCord.Natives.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 621f5065..735f1e98 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -76,6 +76,10 @@ Condition="'$(VcpkgBuildOS)' != 'win' and Exists('vcpkg-non-windows.targets')" /> + + + $(VcpkgPlatformTarget)-$(VcpkgOSTarget) $(VcpkgTriplet)-dynamic @@ -111,7 +115,7 @@ - + - <_CopyOutput Include="%(NativesRuntime.FullPath)" Condition="Exists('%(NativesRuntime.Identity)')"> - %(Filename)%(Extension) + <_CopyOutput Include="%(NativesRuntime.FullPath)"> + %(NativesRuntime.Filename)%(NativesRuntime.Extension) PreserveNewest - + diff --git a/NetCord.Natives/NetCord.Natives.local.targets b/NetCord.Natives/NetCord.Natives.local.targets index 3f730cc0..06e3c54d 100644 --- a/NetCord.Natives/NetCord.Natives.local.targets +++ b/NetCord.Natives/NetCord.Natives.local.targets @@ -1,6 +1,6 @@ - + @@ -18,7 +18,8 @@ %(_NetCordStaticDir.Identity)\lib - $([System.IO.Path]::GetDirectoryName('%(_NetCordRuntimesDir.FullPath)')) + $([System.IO.Path]::GetDirectoryName('%(_NetCordRuntimesDir.FullPath)')) diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets index 93d835ee..0e8c8d0f 100644 --- a/NetCord.Natives/NetCord.Natives.targets +++ b/NetCord.Natives/NetCord.Natives.targets @@ -34,9 +34,9 @@ Condition="'$(PublishAot)' == 'true' and '%(_NetCordStaticLink.Identity)' != ''"/> <_RunExclude Include="$(NetCordNativesRuntimesDir)\**\native\%(_NetCordExcluded.Identity)*.*" - Condition="'@(_NetCordExcluded.Identity)' != ''" /> + Condition="'@(_NetCordExcluded.Identity)' != '' and '$(NetCordNativesRuntimesDir)' != ''" /> <_RunExclude Include="$(NetCordNativesRuntimesDir)\**\native\lib%(_NetCordExcluded.Identity)*.*" - Condition="'@(_NetCordExcluded.Identity)' != ''" /> + Condition="'@(_NetCordExcluded.Identity)' != '' and '$(NetCordNativesRuntimesDir)' != ''" /> diff --git a/NetCord.slnx b/NetCord.slnx index 2338dbc5..30dd9aff 100644 --- a/NetCord.slnx +++ b/NetCord.slnx @@ -84,8 +84,7 @@ - - + @@ -99,7 +98,6 @@ - diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj index 2eade721..2fae99ab 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj @@ -9,6 +9,7 @@ true true true + true false ..\..\..\..\NetCord.Natives diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs index 111e3a69..bf91f09c 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs @@ -25,66 +25,8 @@ private static void Main() Console.WriteLine("NetCord native ahead of time publish app."); Console.WriteLine($"Dave Max Supported Protocol Version: {NativeProbes.DaveMaxSupportedProtocolVersion()}"); - Console.WriteLine($"Sodium Init: {NativeProbes.SodiumInit()}"); + Console.WriteLine($"Sodium Init: {NativeProbes.SodiumInit()}. 0 = OK"); Console.WriteLine($"Opus Version String: {Marshal.PtrToStringAnsi(NativeProbes.OpusGetVersionString())}"); Console.WriteLine($"Zstd Version Number: {NativeProbes.ZstdVersionNumber()}"); - - var cwd = Path.GetFullPath(Directory.GetCurrentDirectory()); - Console.WriteLine($"Current working directory: {cwd}"); - - string[] libraries = new[] { "libdave", "libsodium", "opus", "zstd" }; - var process = Process.GetCurrentProcess(); - var modules = process.Modules; - - bool allUnderCwd = true; - - foreach (var lib in libraries) - { - ProcessModule? found = null; - foreach (ProcessModule m in modules) - { - if (!string.IsNullOrEmpty(m.FileName) && m.FileName.IndexOf(lib, StringComparison.OrdinalIgnoreCase) >= 0) - { - found = m; - break; - } - if (!string.IsNullOrEmpty(m.ModuleName) && m.ModuleName.IndexOf(lib, StringComparison.OrdinalIgnoreCase) >= 0) - { - found = m; - break; - } - } - - if (found == null) - { - Console.WriteLine($"Library '{lib}' not found among loaded modules."); - allUnderCwd = false; - continue; - } - - Console.WriteLine($"{lib} loaded from: {found.FileName}"); - if (!IsUnderDirectory(found.FileName, cwd)) - { - Console.WriteLine($"Library '{lib}' is not under current working directory."); - allUnderCwd = false; - } - } - - Environment.Exit(allUnderCwd ? 0 : 1); - } - - private static bool IsUnderDirectory(string path, string directory) - { - try - { - var fullPath = Path.GetFullPath(path); - var fullDir = Path.GetFullPath(directory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; - var comparison = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return fullPath.StartsWith(fullDir, comparison); - } - catch - { - return false; - } } } diff --git a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs index b47e24bb..f0bc87c6 100644 --- a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs +++ b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs @@ -80,25 +80,42 @@ public void AllLibraryImportsExistInBinary(string libName, string className) [DataRow("libdave;libsodium;opus;zstd")] public void NativeAotStaticLinking(string libName) { + var projectDirectory = Path.Combine(AppContext.BaseDirectory, "Assets", "NativeAotApp"); + var projectFile = Path.Combine(projectDirectory, "NativeAotApp.csproj"); + var generatedProjectFile = Path.Combine(projectDirectory, "NativeAotApp.g.csproj"); + try { + var originalProjectFileContents = File.ReadAllText(projectFile); + var generatedProjectFileContents = originalProjectFileContents.Replace("$(NetCordDirectPInvoke)", libName); + File.WriteAllText(generatedProjectFile, generatedProjectFileContents); + // get NetCordNativesDir from AssemblyMetadata attribute var assembly = typeof(NativesBuildTests).Assembly; - var nativesDir = assembly.GetCustomAttribute()?.Value; + var nativesDir = assembly.GetCustomAttributes()? + .FirstOrDefault(a => a.Key == "NetCordNativesDir")?.Value; Assert.IsNotNull(nativesDir, "NetCordNativesDir metadata attribute is not defined."); + var vcpkgRoot = assembly.GetCustomAttributes()? + .FirstOrDefault(a => a.Key == "VcpkgRoot")?.Value; + Assert.IsNotNull(vcpkgRoot, "VcpkgRoot metadata attribute is not defined."); + var targetFramework = assembly.GetCustomAttributes()? + .FirstOrDefault(a => a.Key == "TargetFramework")?.Value; + Assert.IsNotNull(targetFramework, "TargetFramework metadata attribute is not defined."); // build asset NativeAotApp with Native AoT enabled var buildProcess = new System.Diagnostics.Process(); buildProcess.StartInfo.FileName = "dotnet"; buildProcess.StartInfo.ArgumentList.Add("publish"); + buildProcess.StartInfo.ArgumentList.Add("NativeAotApp.g.csproj"); buildProcess.StartInfo.ArgumentList.Add("-p:Configuration=Release"); + buildProcess.StartInfo.ArgumentList.Add($"-p:TargetFramework={targetFramework}"); buildProcess.StartInfo.ArgumentList.Add("-p:RuntimeIdentifier=" + RuntimeInformation.RuntimeIdentifier); buildProcess.StartInfo.ArgumentList.Add($"-p:NetCordNativesDir={nativesDir}"); - buildProcess.StartInfo.ArgumentList.Add($"-p:NetCordDirectPInvoke=\"{libName}\""); + buildProcess.StartInfo.ArgumentList.Add($"-p:VcpkgRoot={vcpkgRoot}"); - TestContext.WriteLine($"Building Native AoT app: 'dotnet {buildProcess.StartInfo.ArgumentList.Aggregate((a, b) => $"{a} {b}")}'"); + TestContext.WriteLine($"Building Native AoT app in ({projectDirectory}): 'dotnet {buildProcess.StartInfo.ArgumentList.Aggregate((a, b) => $"{a} {b}")}'"); - buildProcess.StartInfo.WorkingDirectory = Path.Combine(AppContext.BaseDirectory, "Assets", "NativeAotApp"); + buildProcess.StartInfo.WorkingDirectory = projectDirectory; buildProcess.StartInfo.RedirectStandardOutput = true; buildProcess.StartInfo.RedirectStandardError = true; buildProcess.Start(); @@ -111,8 +128,10 @@ public void NativeAotStaticLinking(string libName) // check that the library is running without errors, which indicates that it was statically linked successfully var aotProcess = new System.Diagnostics.Process(); - aotProcess.StartInfo.FileName = Path.Combine(AppContext.BaseDirectory, "Assets", "NativeAotApp", - "bin", "release", RuntimeInformation.RuntimeIdentifier, "publish", "NativeAotApp.exe"); + aotProcess.StartInfo.FileName = Path.Combine(projectDirectory, "bin", "release", targetFramework, + RuntimeInformation.RuntimeIdentifier, "publish", + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? + "NativeAotApp.g.exe" : "NativeAotApp.g"); TestContext.WriteLine($"Running Native AoT app: '{aotProcess.StartInfo.FileName}'"); diff --git a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj index 9ddd5a5b..4eaa6e27 100644 --- a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj +++ b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj @@ -35,6 +35,14 @@ <_Parameter1>NetCordNativesDir <_Parameter2>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(NetCordNativesDir)')) + + <_Parameter1>VcpkgRoot + <_Parameter2>$(VcpkgRoot) + + + <_Parameter1>TargetFramework + <_Parameter2>$(TargetFramework) + From 5e2ab688eda8441d1e26b365df8c67429615dd4d Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Sat, 9 May 2026 01:30:34 +0900 Subject: [PATCH 09/16] refactor native build/test pipeline - add reusable vcpkg setup - pack per-RID native nupkgs - streamline NativeAOT test logging - tighten native linking targets --- .github/actions/setup-vcpkg/action.yml | 43 ++++ .github/workflows/build-and-publish.yml | 10 +- .github/workflows/build-natives.yml | 182 +++++--------- .github/workflows/build.yml | 18 +- NetCord.Natives.slnx | 20 ++ NetCord.Natives/NetCord.Natives.csproj | 3 +- NetCord.Natives/NetCord.Natives.targets | 35 ++- .../Assets/NativeAotApp/NativeAotApp.csproj | 6 + .../Assets/NativeAotApp/Program.cs | 35 +-- Tests/NetCord.Natives.Tests/NativeProbes.cs | 78 ++++++ .../NativesBuildTests.cs | 225 +++++++++--------- .../NetCord.Natives.Tests.csproj | 23 +- 12 files changed, 378 insertions(+), 300 deletions(-) create mode 100644 .github/actions/setup-vcpkg/action.yml create mode 100644 Tests/NetCord.Natives.Tests/NativeProbes.cs diff --git a/.github/actions/setup-vcpkg/action.yml b/.github/actions/setup-vcpkg/action.yml new file mode 100644 index 00000000..58416aea --- /dev/null +++ b/.github/actions/setup-vcpkg/action.yml @@ -0,0 +1,43 @@ +name: Setup vcpkg +description: Setup vcpkg with fallback to submodule checkout + +runs: + using: composite + steps: + - name: Resolve or checkout vcpkg + shell: pwsh + run: | + # Ensure vcpkg cache and downloads directories exist + New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null + New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null + + $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT + if (-not $vcpkgRoot) { + $vcpkgCommand = Get-Command vcpkg -ErrorAction SilentlyContinue + if ($vcpkgCommand) { + $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source + } + } + + if (-not $vcpkgRoot -or -not (Test-Path $vcpkgRoot)) { + Write-Host "vcpkg not found in runner image, checking out from submodule..." + git config --file .gitmodules --get-regexp path | while-object { $_.Split()[-1] | where-object { $_ -match 'vcpkg' } } | ForEach-Object { + git submodule update --init --recursive $_ + } + $vcpkgRoot = Join-Path $env:GITHUB_WORKSPACE "vcpkg" + if (-not (Test-Path $vcpkgRoot)) { + Write-Error "vcpkg submodule not found and vcpkg executable not available" + exit 1 + } + } + + if (Test-Path $vcpkgRoot) { + Write-Host "Bootstrapping vcpkg from: $vcpkgRoot" + if ($IsWindows) { + & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics + } else { + & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics + } + } + + "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index a27c0d24..c9de0054 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -18,8 +18,8 @@ jobs: - name: Download Build Artifacts uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with: - name: Build Artifacts - path: artifacts/build + name: NuGet Packages + path: artifacts/pkgs - name: Download Documentation Artifacts uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a @@ -39,11 +39,7 @@ jobs: env: KEY: ${{ secrets.NUGET_API_KEY }} run: | - dotnet nuget push artifacts/build/NetCord/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push artifacts/build/NetCord.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push artifacts/build/Hosting/NetCord.Hosting/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push artifacts/build/Hosting/NetCord.Hosting.Services/bin/Release/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push artifacts/build/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 - name: Deploy Documentation uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index c56bd99c..a5079949 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -1,7 +1,7 @@ name: Build, Test, and Package NetCord.Natives on: - workflow_dispatch: {} + workflow_dispatch: push: paths: - 'NetCord.Natives/**' @@ -17,6 +17,12 @@ jobs: CI: true VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads + VcpkgOSTarget: ${{ matrix.vcpkg-os-target }} + VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }} + Configuration: Release + RuntimeIdentifier: ${{ matrix.rid }} + DotnetVerbose: minimal + strategy: fail-fast: false matrix: @@ -26,15 +32,15 @@ jobs: vcpkg-os-target: windows vcpkg-platform-target: x64 - rid: win-arm64 - runs-on: windows-latest + runs-on: windows-11-arm vcpkg-os-target: windows vcpkg-platform-target: arm64 - rid: osx-x64 - runs-on: macos-latest + runs-on: macos-15-intel vcpkg-os-target: osx vcpkg-platform-target: x64 - rid: osx-arm64 - runs-on: macos-latest + runs-on: macos-15 vcpkg-os-target: osx vcpkg-platform-target: arm64 - rid: linux-x64 @@ -42,83 +48,62 @@ jobs: vcpkg-os-target: linux vcpkg-platform-target: x64 - rid: linux-arm64 - runs-on: ubuntu-latest + runs-on: ubuntu-24.04-arm vcpkg-os-target: linux vcpkg-platform-target: arm64 steps: - name: Checkout uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 - - name: Cache vcpkg installs - uses: actions/cache@v5.0.5 + - name: Restore vcpkg cache + uses: actions/cache/restore@v5.0.5 with: path: | .vcpkg-cache .vcpkg-downloads - key: vcpkg-${{ runner.os }}-${{ matrix.rid }}- - ${{ hashFiles( - 'NetCord.Natives/vcpkg.json', - 'NetCord.Natives/natives-ports/**' - ) }} + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json', 'NetCord.Natives/natives-ports/**') }} restore-keys: | vcpkg-${{ runner.os }}-${{ matrix.rid }}- vcpkg-${{ runner.os }}- - - name: Resolve vcpkg from runner image - shell: pwsh - run: | - # Ensure vcpkg cache and downloads directories exist - New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null - New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null - - $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT - if (-not $vcpkgRoot) { - $vcpkgCommand = Get-Command vcpkg -ErrorAction Stop - $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source - } + - name: Setup vcpkg + uses: ./.github/actions/setup-vcpkg - if (Test-Path $vcpkgRoot) { - # Bootstrap vcpkg - if ($IsWindows) { - & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics - } else { - & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics - } - } - - "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v5.2.0 + with: + global-json-file: global.json - name: Install native build tools (macOS) if: runner.os == 'macOS' shell: bash run: | brew update - brew install autoconf automake libtool pkg-config - - - name: Install ARM64 cross-compiler (linux-arm64) - if: matrix.rid == 'linux-arm64' - shell: bash - run: | - sudo apt-get update - sudo apt-get install -yq gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross + brew install autoconf automake libtool - name: Restore shell: pwsh run: | - dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v normal - - name: Build native outputs for ${{ matrix.rid }} + - name: Build natives projects for ${{ matrix.rid }} shell: pwsh - run: | - dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:GeneratePackageOnBuild=false -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} + run: > # Building tests will build dependencies including the native libraries + dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} + -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" + -p:GeneratePackageOnBuild=false - - name: Test native outputs for ${{ matrix.rid }} + - name: Test natives outputs for ${{ matrix.rid }} shell: pwsh - run: | - dotnet test NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -c Release -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgOSTarget=${{ matrix.vcpkg-os-target }} -p:VcpkgPlatformTarget=${{ matrix.vcpkg-platform-target }} --verbosity normal + run: > + dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + --logger GitHubActions - name: List built for ${{ matrix.rid }} + if: ${{ always() }} shell: pwsh run: | $rid = '${{ matrix.rid }}' @@ -131,98 +116,49 @@ jobs: foreach ($folder in @('bin','lib')) { $path = "NetCord.Natives/bin/$rid/$variant/$triplet/$folder" if (Test-Path $path) { - Write-Host "Contents of: $path" - Get-ChildItem -Path $path -Recurse -Force | Select-Object FullName, Mode, Length, LastWriteTime + Get-ChildItem -Path $path -Recurse } else { - Write-Host "[Info]Not found: $path" + Write-Host "[Info] Not found: $path" } } } } - - name: Upload artifact - uses: actions/upload-artifact@v7.0.1 - with: - name: ${{ matrix.rid }} - path: NetCord.Natives/bin/${{ matrix.rid }} - - pack-natives: - needs: build-natives - runs-on: ubuntu-latest - env: - CI: true - VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite - VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads - VcpkgArtifactsRoot: ${{ github.workspace }}/artifacts - - steps: - - name: Checkout - uses: actions/checkout@v6.0.2 - - - name: Download native artifacts - uses: actions/download-artifact@v8.0.1 - with: - path: artifacts - merge-multiple: false - - - name: Resolve vcpkg from runner image - shell: pwsh - run: | - # Ensure vcpkg cache and downloads directories exist - New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null - New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null - - $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT - if (-not $vcpkgRoot) { - $vcpkgCommand = Get-Command vcpkg -ErrorAction Stop - $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source - } - - if (Test-Path $vcpkgRoot) { - # Bootstrap vcpkg - if ($IsWindows) { - & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics - } else { - & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics - } - } - - "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - - - name: Restore (required for pack) + - name: Pack NuGet Package for ${{ matrix.rid }} shell: pwsh - run: | - dotnet restore NetCord.Natives/NetCord.Natives.csproj -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgEnabled=false + run: > + dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + -o NetCord.Natives/bin/${{ matrix.rid }} + -p:CI=false - - name: Build cross-platform .NET (required for pack) - shell: pwsh - run: | - dotnet build NetCord.Natives/NetCord.Natives.csproj -c Release --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgEnabled=false - - - name: Pack combined nupkg - shell: pwsh - run: | - dotnet pack NetCord.Natives/NetCord.Natives.csproj -c Release --no-build --no-restore -p:VcpkgRoot=$env:VCPKG_ROOT -p:VcpkgArtifactsRoot=$env:VcpkgArtifactsRoot -o $env:VcpkgArtifactsRoot/package - - - name: Upload nupkg + - name: Upload NuGet Package Artifact uses: actions/upload-artifact@v7.0.1 with: - name: NetCord.Natives.Package - path: artifacts/package/*.nupkg + name: NetCord.Natives.${{ matrix.rid }}.nupkg + path: NetCord.Natives/bin/${{ matrix.rid }}/*.nupkg + + - name: Save vcpkg cache + if: ${{ always() }} + uses: actions/cache/save@v5.0.5 + with: + path: | + .vcpkg-cache + .vcpkg-downloads + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json', 'NetCord.Natives/natives-ports/**') }} publish: - needs: pack-natives + needs: [build-test-natives] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - - name: Download nupkg + - name: Download All NuGet Package Artifacts uses: actions/download-artifact@v8.0.1 with: - name: NetCord.Natives.Package - path: artifacts/package + path: artifacts/pkgs + pattern: NetCord.Natives*.nupkg - - name: Publish Package + - name: Publish packages env: KEY: ${{ secrets.NUGET_API_KEY }} run: | - dotnet nuget push artifacts/package/*.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 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 89f48496..d6c0ce12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,9 @@ jobs: - name: Restore dependencies shell: *dev-shell - run: dotnet restore + run: | + dotnet restore NetCord.slnx + dotnet restore NetCord.Natives.slnx -p:VcpkgRoot=$VCPKG_INSTALLATION_ROOT -p:VcpkgEnabled=false - name: Build shell: *dev-shell @@ -68,16 +70,16 @@ jobs: npm run test npm run build - - name: Upload Build Artifacts + - name: Upload NuGet Package Artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: Build Artifacts + name: NuGet Packages 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 + 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 - name: Upload Documentation Artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/NetCord.Natives.slnx b/NetCord.Natives.slnx index 1f71c569..8e306060 100644 --- a/NetCord.Natives.slnx +++ b/NetCord.Natives.slnx @@ -1,7 +1,27 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 735f1e98..3d38cf8c 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -157,7 +157,7 @@ + Returns="@(_CopyOutput)"> <_CopyOutput Include="%(NativesRuntime.FullPath)"> @@ -166,6 +166,7 @@ + diff --git a/NetCord.Natives/NetCord.Natives.targets b/NetCord.Natives/NetCord.Natives.targets index 0e8c8d0f..bdb1a6f6 100644 --- a/NetCord.Natives/NetCord.Natives.targets +++ b/NetCord.Natives/NetCord.Natives.targets @@ -1,23 +1,40 @@ - + - <_NetCordStaticLink Include="libdave;mlspp;bytes;tls_syntax;hpke;libcrypto" - Condition="'%(DirectPInvoke.Identity)' == 'libdave'" /> - <_NetCordStaticLink Include="libsodium" + + + <_NetCordStaticLink Include="libsodium;sodium" Condition="'%(DirectPInvoke.Identity)' == 'libsodium'" /> - <_NetCordStaticLink Include="opus" - Condition="'%(DirectPInvoke.Identity)' == 'opus'" /> - <_NetCordStaticLink Include="zstd" - Condition="'%(DirectPInvoke.Identity)' == 'zstd'" /> + <_NetCordStaticLink Include="libdave;dave" + Condition="'%(DirectPInvoke.Identity)' == 'libdave'" /> + + + <_NetCordStaticLink Include="mlspp;hpke;bytes;tls_syntax" + Condition="'%(DirectPInvoke.Identity)' == 'libdave'" /> + + + <_NetCordStaticLink Include="opus;zstd" + Condition="'%(DirectPInvoke.Identity)' == 'opus' or '%(DirectPInvoke.Identity)' == 'zstd'" /> + + + <_NetCordStaticLink Include="libcrypto;crypto" + Condition="'%(DirectPInvoke.Identity)' == 'libdave'" /> - + + + + true + true true false + $(NoWarn);IL2075;IL2026 ..\..\..\..\NetCord.Natives + + + + + diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs index bf91f09c..6581e697 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/Program.cs @@ -1,32 +1,9 @@ -using System; -using System.Diagnostics; -using System.IO; using System.Runtime.InteropServices; +using NetCord.Natives.Tests; -internal static partial class NativeProbes -{ - [LibraryImport("libdave", EntryPoint = "daveMaxSupportedProtocolVersion")] - internal static partial uint DaveMaxSupportedProtocolVersion(); +Console.WriteLine("NetCord native ahead of time publish app."); - [LibraryImport("libsodium", EntryPoint = "sodium_init")] - internal static partial int SodiumInit(); - - [LibraryImport("opus", EntryPoint = "opus_get_version_string")] - internal static partial nint OpusGetVersionString(); - - [LibraryImport("zstd", EntryPoint = "ZSTD_versionNumber")] - internal static partial uint ZstdVersionNumber(); -} - -internal static class Program -{ - private static void Main() - { - 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())}"); - Console.WriteLine($"Zstd Version Number: {NativeProbes.ZstdVersionNumber()}"); - } -} +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())}"); +Console.WriteLine($"Zstd Version Number: {NativeProbes.ZstdVersionNumber()}"); diff --git a/Tests/NetCord.Natives.Tests/NativeProbes.cs b/Tests/NetCord.Natives.Tests/NativeProbes.cs new file mode 100644 index 00000000..c8e95ef7 --- /dev/null +++ b/Tests/NetCord.Natives.Tests/NativeProbes.cs @@ -0,0 +1,78 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +namespace NetCord.Natives.Tests; + +public static partial class NativeProbes +{ + [LibraryImport("libdave", EntryPoint = "daveMaxSupportedProtocolVersion")] + internal static partial uint 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(); + + internal static IReadOnlyList GetMissingLibraryImports(string libName, string className, Assembly assemblyWithImports) + { + var typeWithImports = assemblyWithImports.GetType(className, true); + var libHandle = GetLoadedNativeModuleHandle(libName); + var missingExports = new List(); + + var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + .Select(m => new + { + MethodName = m.Name, + Attr = m.GetCustomAttribute(), + }) + .Where(x => x.Attr != null) + .ToArray(); + + if (methods.Length == 0) + throw new InvalidOperationException($"No methods with [LibraryImport] found in '{className}'."); + + foreach (var item in methods) + { + // Use EntryPoint if defined, otherwise fallback to method name. + string exportName = item.Attr!.EntryPoint ?? item.MethodName; + + if (!NativeLibrary.TryGetExport(libHandle, exportName, out _)) + { + missingExports.Add(exportName); + } + } + + return missingExports; + } + + internal static IntPtr GetLoadedNativeModuleHandle(string libName) + { + _ = libName switch + { + "libdave" => (object)DaveMaxSupportedProtocolVersion(), + "libsodium" => (object)SodiumInit(), + "opus" => (object)OpusGetVersionString(), + "zstd" => (object)ZstdVersionNumber(), + _ => throw new InvalidOperationException($"Unknown library name '{libName}' provided to test."), + }; + + var module = System.Diagnostics.Process.GetCurrentProcess().Modules + .Cast() + .FirstOrDefault(m => + { + var moduleName = Path.GetFileName(m.ModuleName); + 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)) + return libHandleByPath; + + throw new InvalidOperationException($"Failed to obtain a handle for native module '{libName}'."); + } +} diff --git a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs index f0bc87c6..f2462585 100644 --- a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs +++ b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; @@ -7,9 +7,6 @@ namespace NetCord.Natives.Tests; [TestClass] public class NativesBuildTests { - // MSTest automatically injects this property - public TestContext TestContext { get; set; } - [TestMethod] [DataRow("libdave")] [DataRow("libsodium")] @@ -17,14 +14,14 @@ public class NativesBuildTests [DataRow("zstd")] public void NativesLoaded(string libName) { - try + _ = libName switch { - NativeLibrary.Load(libName); - } - catch (Exception ex) - { - Assert.Fail($"Failed to load library '{libName}': {ex}"); - } + "libdave" => (object)NativeProbes.DaveMaxSupportedProtocolVersion(), + "libsodium" => (object)NativeProbes.SodiumInit(), + "opus" => (object)NativeProbes.OpusGetVersionString(), + "zstd" => (object)NativeProbes.ZstdVersionNumber(), + _ => throw new InvalidOperationException($"Unknown library name '{libName}' provided to test."), + }; } [TestMethod] @@ -34,48 +31,13 @@ public void NativesLoaded(string libName) [DataRow("zstd", "NetCord.Gateway.Compression.Zstandard")] public void AllLibraryImportsExistInBinary(string libName, string className) { - IntPtr libHandle = IntPtr.Zero; - - try - { - var assembly = typeof(NetCord.Application).Assembly; - var typeWithImports = assembly.GetType(className, true); - - libHandle = NativeLibrary.Load(libName); - - var missingExports = new List(); - - // Reflect over methods with [LibraryImport] - var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) - .Select(m => new { - MethodName = m.Name, - Attr = m.GetCustomAttribute() - }) - .Where(x => x.Attr != null); - Assert.IsNotEmpty(methods, $"No methods with [LibraryImport] found in '{className}'."); + var missingExports = NativeProbes.GetMissingLibraryImports(libName, className, typeof(NetCord.Application).Assembly); - foreach (var item in methods) - { - // Use EntryPoint if defined, otherwise fallback to Method Name - string exportName = item.Attr!.EntryPoint ?? item.MethodName; - - if (!NativeLibrary.TryGetExport(libHandle, exportName, out _)) - { - missingExports.Add(exportName); - } - } - Assert.IsEmpty(missingExports, $"The following entry points were not found in '{libName}': {string.Join(", ", missingExports)}"); - } - catch (Exception ex) - { - Assert.Fail($"An error occurred while verifying imports for '{libName}': {ex}"); - } - finally - { - NativeLibrary.Free(libHandle); - } + Assert.IsEmpty(missingExports, $"The following entry points were not found in '{libName}': {string.Join(", ", missingExports)}"); } + const string NativeAotAppLogTag = $"[{nameof(NativeAotStaticLinking)}]"; + [DoNotParallelize] [TestMethod] [DataRow("libdave;libsodium;opus;zstd")] public void NativeAotStaticLinking(string libName) @@ -84,70 +46,107 @@ public void NativeAotStaticLinking(string libName) var projectFile = Path.Combine(projectDirectory, "NativeAotApp.csproj"); var generatedProjectFile = Path.Combine(projectDirectory, "NativeAotApp.g.csproj"); - try + // get properties to be passed to the NativeAotApp build from AssemblyMetadata attribute + var assembly = typeof(NativesBuildTests).Assembly; + + var properties = assembly.GetCustomAttributes()? + .FirstOrDefault(a => a.Key == "NativeAotAppProps")?.Value; + Assert.IsNotNull(properties, "NativeAotAppProps metadata attribute is not defined."); + + // build asset NativeAotApp with Native AoT enabled + var buildProcess = new System.Diagnostics.Process(); + buildProcess.StartInfo.FileName = "dotnet"; + buildProcess.StartInfo.ArgumentList.Add("publish"); + buildProcess.StartInfo.ArgumentList.Add("NativeAotApp.csproj"); + buildProcess.StartInfo.ArgumentList.Add("-tl:off"); + buildProcess.StartInfo.ArgumentList.Add("-v:n"); + buildProcess.StartInfo.ArgumentList.Add($"-p:{properties}"); + + Console.WriteLine($"{NativeAotAppLogTag} Building Native AoT app in ({projectDirectory}): 'dotnet {buildProcess.StartInfo.ArgumentList.Aggregate((a, b) => $"{a} {b}")}'"); + + buildProcess.StartInfo.WorkingDirectory = projectDirectory; + buildProcess.StartInfo.RedirectStandardOutput = true; + buildProcess.OutputDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + }; + buildProcess.StartInfo.RedirectStandardError = true; + buildProcess.ErrorDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + }; + var ok = buildProcess.Start(); + buildProcess.BeginOutputReadLine(); + buildProcess.BeginErrorReadLine(); + buildProcess.WaitForExit(); + + Assert.AreEqual(0, buildProcess.ExitCode, $"Native AoT build failed for '{libName}'."); + + // Obtain the generated RunCommand from a build so we launch the same command the SDK would. + var getRunCmd = new System.Diagnostics.Process(); + getRunCmd.StartInfo.FileName = "dotnet"; + getRunCmd.StartInfo.ArgumentList.Add("build"); + getRunCmd.StartInfo.ArgumentList.Add("NativeAotApp.csproj"); + getRunCmd.StartInfo.ArgumentList.Add($"-p:{properties}"); + getRunCmd.StartInfo.ArgumentList.Add("-t:GetTargetPath"); + getRunCmd.StartInfo.ArgumentList.Add("-getProperty:PublishDir"); + getRunCmd.StartInfo.ArgumentList.Add("--no-restore"); + + string? runCmdOutput = null; + + getRunCmd.StartInfo.WorkingDirectory = projectDirectory; + getRunCmd.StartInfo.RedirectStandardOutput = true; + getRunCmd.OutputDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + { + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + runCmdOutput = e.Data.Trim('\r', '\n', '"'); + } + }; + getRunCmd.StartInfo.RedirectStandardError = true; + getRunCmd.ErrorDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + }; + getRunCmd.Start(); + getRunCmd.BeginErrorReadLine(); + getRunCmd.BeginOutputReadLine(); + getRunCmd.WaitForExit(); + + Assert.AreEqual(0, getRunCmd.ExitCode, $"Failed to obtain PublishDir for '{libName}'."); + Assert.IsFalse(string.IsNullOrEmpty(runCmdOutput), $"PublishDir is empty for '{libName}'."); + + runCmdOutput = Path.Combine(projectDirectory, runCmdOutput, + "NativeAotApp" + (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "")); + + // check that the library is running without errors, which indicates that it was statically linked successfully + var aotProcess = new System.Diagnostics.Process(); + aotProcess.StartInfo.FileName = runCmdOutput; + aotProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(runCmdOutput); + + Console.WriteLine($"{NativeAotAppLogTag} Running Native AoT app: '{runCmdOutput}'"); + + aotProcess.StartInfo.RedirectStandardOutput = true; + aotProcess.OutputDataReceived += (sender, e) => { - var originalProjectFileContents = File.ReadAllText(projectFile); - var generatedProjectFileContents = originalProjectFileContents.Replace("$(NetCordDirectPInvoke)", libName); - File.WriteAllText(generatedProjectFile, generatedProjectFileContents); - - // get NetCordNativesDir from AssemblyMetadata attribute - var assembly = typeof(NativesBuildTests).Assembly; - var nativesDir = assembly.GetCustomAttributes()? - .FirstOrDefault(a => a.Key == "NetCordNativesDir")?.Value; - Assert.IsNotNull(nativesDir, "NetCordNativesDir metadata attribute is not defined."); - var vcpkgRoot = assembly.GetCustomAttributes()? - .FirstOrDefault(a => a.Key == "VcpkgRoot")?.Value; - Assert.IsNotNull(vcpkgRoot, "VcpkgRoot metadata attribute is not defined."); - var targetFramework = assembly.GetCustomAttributes()? - .FirstOrDefault(a => a.Key == "TargetFramework")?.Value; - Assert.IsNotNull(targetFramework, "TargetFramework metadata attribute is not defined."); - - // build asset NativeAotApp with Native AoT enabled - var buildProcess = new System.Diagnostics.Process(); - buildProcess.StartInfo.FileName = "dotnet"; - buildProcess.StartInfo.ArgumentList.Add("publish"); - buildProcess.StartInfo.ArgumentList.Add("NativeAotApp.g.csproj"); - buildProcess.StartInfo.ArgumentList.Add("-p:Configuration=Release"); - buildProcess.StartInfo.ArgumentList.Add($"-p:TargetFramework={targetFramework}"); - buildProcess.StartInfo.ArgumentList.Add("-p:RuntimeIdentifier=" + RuntimeInformation.RuntimeIdentifier); - buildProcess.StartInfo.ArgumentList.Add($"-p:NetCordNativesDir={nativesDir}"); - buildProcess.StartInfo.ArgumentList.Add($"-p:VcpkgRoot={vcpkgRoot}"); - - TestContext.WriteLine($"Building Native AoT app in ({projectDirectory}): 'dotnet {buildProcess.StartInfo.ArgumentList.Aggregate((a, b) => $"{a} {b}")}'"); - - buildProcess.StartInfo.WorkingDirectory = projectDirectory; - buildProcess.StartInfo.RedirectStandardOutput = true; - buildProcess.StartInfo.RedirectStandardError = true; - buildProcess.Start(); - buildProcess.WaitForExit(); - - TestContext.WriteLine($"Build Output of AoT app for '{libName}': {buildProcess.StandardOutput.ReadToEnd()}"); - - Assert.AreEqual(0, buildProcess.ExitCode, - $"Native AoT build failed for '{libName}'. Output: {buildProcess.StandardError.ReadToEnd()}"); - - // check that the library is running without errors, which indicates that it was statically linked successfully - var aotProcess = new System.Diagnostics.Process(); - aotProcess.StartInfo.FileName = Path.Combine(projectDirectory, "bin", "release", targetFramework, - RuntimeInformation.RuntimeIdentifier, "publish", - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? - "NativeAotApp.g.exe" : "NativeAotApp.g"); - - TestContext.WriteLine($"Running Native AoT app: '{aotProcess.StartInfo.FileName}'"); - - aotProcess.StartInfo.RedirectStandardOutput = true; - aotProcess.StartInfo.RedirectStandardError = true; - aotProcess.Start(); - aotProcess.WaitForExit(); - - TestContext.WriteLine($"Output of AoT app for '{libName}': {aotProcess.StandardOutput.ReadToEnd()}"); - - Assert.AreEqual(0, aotProcess.ExitCode, - $"Native AoT app failed to run for '{libName}'. Output: {aotProcess.StandardError.ReadToEnd()}"); - } - catch (Exception ex) + if (!string.IsNullOrEmpty(e.Data)) + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + }; + aotProcess.StartInfo.RedirectStandardError = true; + aotProcess.ErrorDataReceived += (sender, e) => { - Assert.Fail($"Failed to statically link '{libName}' for Native Ahead-of-Time (AoT) compilation: {ex}"); - } + if (!string.IsNullOrEmpty(e.Data)) + Console.WriteLine($"{NativeAotAppLogTag} {e.Data}"); + }; + aotProcess.Start(); + aotProcess.BeginOutputReadLine(); + aotProcess.BeginErrorReadLine(); + aotProcess.WaitForExit(); + + Assert.AreEqual(0, aotProcess.ExitCode, $"Native AoT app failed to run for '{libName}'."); } } diff --git a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj index 4eaa6e27..6dd95eed 100644 --- a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj +++ b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj @@ -4,6 +4,7 @@ net10.0 enable enable + true false true @@ -13,6 +14,8 @@ + @@ -23,25 +26,25 @@ + + ..\..\NetCord.Natives\ + NetCordNativesDir=$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(NetCordNativesDir)')) + + $(VCPKG_ROOT) + $(NativeAotAppProps),VcpkgRoot=$(VcpkgRoot) + + $(NativeAotAppProps),$(AppendNativeAotAppProps) - <_Parameter1>NetCordNativesDir - <_Parameter2>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\$(NetCordNativesDir)')) - - - <_Parameter1>VcpkgRoot - <_Parameter2>$(VcpkgRoot) - - - <_Parameter1>TargetFramework - <_Parameter2>$(TargetFramework) + <_Parameter1>NativeAotAppProps + <_Parameter2>$(NativeAotAppProps) From 355ffd6a0ffe79d6a51fe63754c87616924c4432 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Mon, 11 May 2026 05:49:25 +0900 Subject: [PATCH 10/16] Clean up & atomize CI workflows * Skip testing for OSX due to dyld limitation * Clean up natives packaging * Docs updates for prebuilt natives --- .github/workflows/build-and-publish.yml | 2 + .github/workflows/build-natives.yml | 82 +++++------ .github/workflows/build-publish-natives.yml | 35 +++++ .github/workflows/build.yml | 17 +-- Directory.Packages.props | 1 + .../installing-native-dependencies.md | 138 ++++++++++-------- NetCord.Natives/NativesHelper.cs | 20 --- NetCord.Natives/NetCord.Natives.csproj | 29 ++-- Tests/NetCord.Natives.Tests/NativeProbes.cs | 20 ++- .../NativesBuildTests.cs | 3 + .../NetCord.Natives.Tests.csproj | 1 - 11 files changed, 192 insertions(+), 156 deletions(-) create mode 100644 .github/workflows/build-publish-natives.yml delete mode 100644 NetCord.Natives/NativesHelper.cs diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index c9de0054..1bdd8c0f 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -20,6 +20,7 @@ jobs: with: name: NuGet Packages path: artifacts/pkgs + merge-multiple: true - name: Download Documentation Artifacts uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a @@ -40,6 +41,7 @@ jobs: KEY: ${{ secrets.NUGET_API_KEY }} 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 - name: Deploy Documentation uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index a5079949..6cada1d3 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -1,17 +1,20 @@ -name: Build, Test, and Package NetCord.Natives +name: Build NetCord.Natives on: + workflow_call: workflow_dispatch: + inputs: + GenerateBinLog: + type: boolean + default: false push: paths: - 'NetCord.Natives/**' + - 'Tests/NetCord.Natives.Tests/**' - '.github/workflows/build-natives.yml' - tags: - - "[0-9]+.[0-9]+.[0-9]+" - - "[0-9]+.[0-9]+.[0-9]+-*" jobs: - build-test-natives: + build-natives: runs-on: ${{ matrix.runs-on }} env: CI: true @@ -22,6 +25,7 @@ jobs: Configuration: Release RuntimeIdentifier: ${{ matrix.rid }} DotnetVerbose: minimal + GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }} strategy: fail-fast: false @@ -57,6 +61,7 @@ jobs: uses: actions/checkout@v6.0.2 with: fetch-depth: 0 + filter: tree:0 - name: Restore vcpkg cache uses: actions/cache/restore@v5.0.5 @@ -82,60 +87,56 @@ jobs: shell: bash run: | brew update - brew install autoconf automake libtool + for pkg in autoconf automake libtool; do + brew list $pkg &>/dev/null || brew install $pkg + done - name: Restore shell: pwsh run: | - dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v normal + dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }} - name: Build natives projects for ${{ matrix.rid }} shell: pwsh run: > # Building tests will build dependencies including the native libraries dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" - -p:GeneratePackageOnBuild=false + -p:GeneratePackageOnBuild=false -p:CI=false - name: Test natives outputs for ${{ matrix.rid }} shell: pwsh run: > dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} + --logger "console;verbosity=detailed" --logger GitHubActions - - name: List built for ${{ matrix.rid }} - if: ${{ always() }} - shell: pwsh - run: | - $rid = '${{ matrix.rid }}' - $tripletBase = '${{ matrix.vcpkg-platform-target }}-${{ matrix.vcpkg-os-target }}' - $suffix = if ($IsWindows) { 'static' } else { 'dynamic' } - $triplets = @("$tripletBase", "$tripletBase-$suffix") - - foreach ($variant in @('natives','natives-static')) { - foreach ($triplet in @($triplets)) { - foreach ($folder in @('bin','lib')) { - $path = "NetCord.Natives/bin/$rid/$variant/$triplet/$folder" - if (Test-Path $path) { - Get-ChildItem -Path $path -Recurse - } else { - Write-Host "[Info] Not found: $path" - } - } - } - } - - name: Pack NuGet Package for ${{ matrix.rid }} + if: ${{ always() }} shell: pwsh run: > dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} -o NetCord.Natives/bin/${{ matrix.rid }} -p:CI=false + - name: Upload Binary Logs + if: ${{ env.GenerateBinLog == 'true' && always() }} + uses: actions/upload-artifact@v4.6.0 + with: + name: ${{ matrix.rid }}-binlogs + path: | + *.binlog + - name: Upload NuGet Package Artifact + if: ${{ always() }} uses: actions/upload-artifact@v7.0.1 with: - name: NetCord.Natives.${{ matrix.rid }}.nupkg - path: NetCord.Natives/bin/${{ matrix.rid }}/*.nupkg + name: NetCord.Natives.${{ matrix.rid }}.packages + path: | + NetCord.Natives/bin/${{ matrix.rid }}/*.nupkg + NetCord.Natives/bin/${{ matrix.rid }}/*.snupkg - name: Save vcpkg cache if: ${{ always() }} @@ -145,20 +146,3 @@ jobs: .vcpkg-cache .vcpkg-downloads key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json', 'NetCord.Natives/natives-ports/**') }} - - publish: - needs: [build-test-natives] - if: startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-latest - steps: - - name: Download All NuGet Package Artifacts - uses: actions/download-artifact@v8.0.1 - with: - path: artifacts/pkgs - pattern: NetCord.Natives*.nupkg - - - name: Publish packages - env: - KEY: ${{ secrets.NUGET_API_KEY }} - run: | - dotnet nuget push artifacts/pkgs/*.nupkg -k $KEY -s https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/build-publish-natives.yml b/.github/workflows/build-publish-natives.yml new file mode 100644 index 00000000..8850fb49 --- /dev/null +++ b/.github/workflows/build-publish-natives.yml @@ -0,0 +1,35 @@ +name: Build & Publish NetCord.Natives + +on: + workflow_dispatch: + push: + paths: + - 'NetCord.Natives/**' + - '.github/workflows/build-natives.yml' + - '.github/workflows/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 + + steps: + - name: Download All NuGet Package Artifacts + uses: actions/download-artifact@v8.0.1 + with: + path: artifacts/pkgs + pattern: NetCord.Natives.*.packages + merge-multiple: true + + - name: Publish packages + env: + KEY: ${{ secrets.NUGET_API_KEY }} + 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 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6c0ce12..175eebaf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,11 +51,11 @@ jobs: - 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}' @@ -75,11 +75,8 @@ jobs: with: name: NuGet Packages path: | - 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 + pkgs/*.nupkg + pkgs/*.snupkg - name: Upload Documentation Artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/Directory.Packages.props b/Directory.Packages.props index 794b74bd..099bf452 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,6 +23,7 @@ + diff --git a/Documentation/guides/basic-concepts/installing-native-dependencies.md b/Documentation/guides/basic-concepts/installing-native-dependencies.md index 9c9fe2d4..061d36f0 100644 --- a/Documentation/guides/basic-concepts/installing-native-dependencies.md +++ b/Documentation/guides/basic-concepts/installing-native-dependencies.md @@ -1,91 +1,109 @@ # 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 Context -For HTTP interactions, [Libsodium](https://doc.libsodium.org/installation) is required. +- **Libdave**: Essential for voice connection interactions. +- **Libsodium**: Used for encryption. While NetCord defaults to native AES-GCM (which does not require Libsodium), Libsodium is a highly recommended production dependency. It acts as a fallback for the XChaCha20-Poly1305 encryption mode, ensuring your bot remains compatible if Discord switches to this mode for your connection. +- **Opus**: A versatile audio codec required for any classes in NetCord prefixed with `Opus` (e.g., audio encoding/decoding). +- **Zstd**: Used for efficient payload compression. -## 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 per-RID (Runtime Identifier) packages. This model automates binary resolution, ensuring the correct libraries are provided for your target platform. -## Installation +### Supported Platforms +Packages are available for: -### [Dynamic Linking](#tab/dynamic) +| Platform | RID | NativeAOT Support |
Size
![Storage Requirement](https://img.shields.io/badge/Runtime-Package-blue)
| +|----------|-----|-------------------------|-----------| +| Windows x64 | `win-x64` | βœ“ (Static CRT /MT) | ![Windows x64](https://img.shields.io/badge/6_MB-42_MB_(176_MB)-blue) | +| Windows ARM64 | `win-arm64` | βœ“ (Static CRT /MT) | ![Windows ARM64](https://img.shields.io/badge/6_MB-41_MB_(183_MB)-blue) | +| Linux x64 | `linux-x64` | βœ“ (Dynamic CRT) | ![Linux x64](https://img.shields.io/badge/10_MB-9_MB_(28_MB)-blue) | +| Linux ARM64 | `linux-arm64` | βœ“ (Dynamic CRT) | ![Linux ARM64](https://img.shields.io/badge/10_MB-8_MB_(26_MB)-blue) | +| β“˜ macOS x64 | `osx-x64` | βœ“ (Dynamic CRT) | ![macOS x64](https://img.shields.io/badge/15_MB-11_MB_(28_MB)-blue) | +| β“˜ macOS ARM64 | `osx-arm64` | βœ“ (Dynamic CRT) | ![macOS ARM64](https://img.shields.io/badge/13_MB-10_MB_(25_MB)-blue) | -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). +β“˜ Currently, the macOS packages are built and published, but functions verification tests are skipped due to limitations with `dyld`. +They are still expected to work correctly, but we recommend testing on macOS before production use. -### Manual or System-wide Installation +## Dynamic Linking +For standard .NET applications, you can simply reference the relevant packages for your target platforms. The runtimes will be correctly copied and loaded across platforms. -#### Windows - -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. - -- Place these files in the runtime directory of your application. This is the folder where your application's executable is located. - -#### Linux and MacOS - -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. - -- 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 - - - - - - - - - - - ``` +```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. +## Usage with 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. +### Requirement for DirectPInvoke +When targeting NativeAOT, you must ensure that all used native libraries are explicitly registered using `` in your project file to ensure they are properly included during the AOT compilation process: -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. +### Excluding Bundled Dependencies +If you have provided your own native binaries and need to exclude the ones bundled in the NetCord NuGet package to avoid conflicts, use the `NetCordExcludeNatives` property. + +```xml + + opus + +``` -*** +## Custom Manual/System-wide Installation -#### Installation External Links +If you are developing for an unsupported platform or require a custom-built native binary, you may choose to handle native dependencies manually. + +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. + +### Installation External Links | Library | Installation 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 +- If you encounter issues with native dependencies, ensure that the correct versions are installed and that they are 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 automatically 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 | + +### How It’s Built +* **Reproducible builds**: Dependencies are strictly pinned using [vcpkg](https://github.com/microsoft/vcpkg) baselines. This means every build result should be identical, regardless of who or what runs the build. diff --git a/NetCord.Natives/NativesHelper.cs b/NetCord.Natives/NativesHelper.cs deleted file mode 100644 index 866a421b..00000000 --- a/NetCord.Natives/NativesHelper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace NetCord.Natives; - -[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] -public class NativeLibraryVersionAttribute(string name, string version) : Attribute -{ - public string Name { get; } = name; - public string Version { get; } = version; -} - -public static class NativesHelper -{ - public static IEnumerable GetNativeLibraryVersions() - { - return typeof(NativesHelper).Assembly.GetCustomAttributes(); - } -} diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index 3d38cf8c..a13b761d 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -3,6 +3,9 @@ Pre-built native libraries for NetCord, $(Description) false + false + false + true $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..')) @@ -123,7 +126,7 @@ Condition="'$(VcpkgUseStatic)' != 'true'" />
- @@ -131,29 +134,27 @@ - + @(StatusLines, ' ') - + <_VcpkgPkg Include="@(NativeLibLic)"> - - $([System.Text.RegularExpressions.Regex]::Match('$(StatusText)', 'Package: %(Identity)\n(?:.*\n)*?Version: (.*?)\n').Groups[1].Value) + + $([System.Text.RegularExpressions.Regex]::Match('$(StatusText)', 'Package: %(Identity)\n(?:.*\n)*?Version: (.*?)\n').Groups[1].Value) - - - - <_Parameter1>%(_VcpkgPkg.Identity) - <_Parameter2>%(_VcpkgPkg.Version) - - - + + + $(PackageDescription) (Includes: @(_VcpkgPkg->'%(Identity) v%(Version)', ', ')) + + - + GetMissingLibraryImports(string libName, s return missingExports; } + /* + * 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 @@ -60,19 +70,25 @@ internal static IntPtr GetLoadedNativeModuleHandle(string libName) _ => 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.ModuleName); + 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 '{libName}'."); + throw new InvalidOperationException($"Failed to obtain a handle for native module '{module.ModuleName}'."); } } diff --git a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs index f2462585..8de10c24 100644 --- a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs +++ b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs @@ -25,6 +25,7 @@ public void NativesLoaded(string libName) } [TestMethod] + [OSCondition(ConditionMode.Exclude, OperatingSystems.OSX)] [DataRow("libdave", "NetCord.Gateway.Voice.Dave")] [DataRow("libsodium", "NetCord.Gateway.Voice.Encryption.XChaCha20Poly1305")] [DataRow("opus", "NetCord.Gateway.Voice.Opus")] @@ -93,6 +94,8 @@ public void NativeAotStaticLinking(string libName) getRunCmd.StartInfo.ArgumentList.Add("-t:GetTargetPath"); getRunCmd.StartInfo.ArgumentList.Add("-getProperty:PublishDir"); getRunCmd.StartInfo.ArgumentList.Add("--no-restore"); + + getRunCmd.StartInfo.ArgumentList.Add("--bl"); string? runCmdOutput = null; diff --git a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj index 6dd95eed..636b6f9a 100644 --- a/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj +++ b/Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj @@ -27,7 +27,6 @@ - From 041858d765b791db65d522ffae0ad261f0ddb24c Mon Sep 17 00:00:00 2001 From: Haves Irfan Date: Fri, 22 May 2026 03:29:03 +0900 Subject: [PATCH 11/16] Apply typos and internals fixes Co-authored-by: Kuba_Z2 <77853483+KubaZ2@users.noreply.github.com> --- .../installing-native-dependencies.md | 14 +++++++------- NetCord.Natives/natives-ports/libdave/vcpkg.json | 2 +- NetCord.slnx | 1 - Tests/NetCord.Natives.Tests/NativeProbes.cs | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Documentation/guides/basic-concepts/installing-native-dependencies.md b/Documentation/guides/basic-concepts/installing-native-dependencies.md index 061d36f0..c6791906 100644 --- a/Documentation/guides/basic-concepts/installing-native-dependencies.md +++ b/Documentation/guides/basic-concepts/installing-native-dependencies.md @@ -97,13 +97,13 @@ The native packaging model is designed to make managing dependencies as transpar ### Built-in Compliance All necessary licenses and copyright notices from the original native project sources are bundled automatically 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 | +| 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 | ### How It’s Built * **Reproducible builds**: Dependencies are strictly pinned using [vcpkg](https://github.com/microsoft/vcpkg) baselines. This means every build result should be identical, regardless of who or what runs the build. diff --git a/NetCord.Natives/natives-ports/libdave/vcpkg.json b/NetCord.Natives/natives-ports/libdave/vcpkg.json index 9f74f4d3..9a95c533 100644 --- a/NetCord.Natives/natives-ports/libdave/vcpkg.json +++ b/NetCord.Natives/natives-ports/libdave/vcpkg.json @@ -15,4 +15,4 @@ "host": true } ] -} \ No newline at end of file +} diff --git a/NetCord.slnx b/NetCord.slnx index 30dd9aff..23417afd 100644 --- a/NetCord.slnx +++ b/NetCord.slnx @@ -84,7 +84,6 @@ - diff --git a/Tests/NetCord.Natives.Tests/NativeProbes.cs b/Tests/NetCord.Natives.Tests/NativeProbes.cs index 4a03b6d2..14338f93 100644 --- a/Tests/NetCord.Natives.Tests/NativeProbes.cs +++ b/Tests/NetCord.Natives.Tests/NativeProbes.cs @@ -23,7 +23,7 @@ internal static IReadOnlyList GetMissingLibraryImports(string libName, s var libHandle = GetLoadedNativeModuleHandle(libName); var missingExports = new List(); - var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.NonPublic) .Select(m => new { MethodName = m.Name, From 50f0e3e7b8cdc97a537bffca64e03e6dbf64f032 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 23:44:57 +0900 Subject: [PATCH 12/16] Resolve PR comments * Implement resolved PR #257 review comments - Fix NetCord.Natives.targets comment typo: 'comes' -> 'come' - Normalize Importance='High' to 'high' in NetCord.Natives.csproj - Remove stale commented-out PackageReference in NativeAotApp.csproj - Update Resources/NuGet/README.md to link to docs for full package list - Add 'natives' devShell to flake.nix with autoconf/automake/libtool - Replace macOS brew step with Nix in build-natives.yml; split Build step for Windows/non-Windows - Pin all GitHub Actions by commit hash in build-natives.yml - Rename build-publish-natives.yml -> build-and-publish-natives.yml; pin download-artifact hash; fix self-reference in paths trigger Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/f6e9307c-fd0a-40c8-b3a8-e0484782c21e Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * fix: address natives README link and reflection method visibility Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/e686bf59-4e1e-4ec5-82f8-cc6b3ef93656 Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * README: add period to NetCord.Natives table description Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/0553c8bd-a710-4a4d-a8a8-deb3dc917faa Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Deduplicate native build workflow step and remove MSBuild XML schema namespaces Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/a0011395-8ab0-458e-a04e-8152069b7880 Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Fix README NetCord.Natives description punctuation Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/a0011395-8ab0-458e-a04e-8152069b7880 Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Revert prior README tweak and set NetCord.Natives row text as requested Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/52fb7ee0-c97d-452c-9d94-1eec13cd17ee Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Set README NetCord.Natives row to exact requested text Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/5f1c09c3-27c2-48af-872c-0ae465ec420b Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Update README natives row, native dependencies docs, and test configs - Update all README.md files with new NetCord.Natives. row format - Replace size column with NuGet package badges in native dependencies table - Clarify libsodium description regarding voice server encryption requirements - Update NativeAotApp.csproj: change DirectPInvoke to directly include libraries - Remove CentrallyManagedPackage false and NoWarn settings from NativeAotApp.csproj - Remove stray -bl argument from NativesBuildTests.cs GetRunCmd Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/e244793a-3f65-4653-8019-ee2d5151b0c1 Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Improve libsodium documentation with clearer explanation of encryption fallback scenarios Agent-Logs-Url: https://github.com/ha-ves/NetCord/sessions/2a7fe8b8-026b-4918-8d18-9356084ad340 Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> * Fix README for NetCord.Natives * fix readme in nuget --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ha-ves <20160532+ha-ves@users.noreply.github.com> Co-authored-by: Haves Irfan fix CI shell error --- ...ives.yml => build-and-publish-natives.yml} | 4 +- .github/workflows/build-natives.yml | 116 +++++++++++------- .../installing-native-dependencies.md | 20 +-- NetCord.Natives/NetCord.Natives.csproj | 2 +- NetCord.Natives/NetCord.Natives.local.targets | 2 +- NetCord.Natives/NetCord.Natives.props | 2 +- NetCord.Natives/NetCord.Natives.targets | 4 +- NetCord.Natives/vcpkg-non-windows.targets | 2 +- README.md | 2 +- Resources/NuGet/README.md | 2 +- .../Assets/NativeAotApp/NativeAotApp.csproj | 8 +- Tests/NetCord.Natives.Tests/NativeProbes.cs | 2 +- .../NativesBuildTests.cs | 2 - flake.nix | 8 ++ 14 files changed, 110 insertions(+), 66 deletions(-) rename .github/workflows/{build-publish-natives.yml => build-and-publish-natives.yml} (85%) diff --git a/.github/workflows/build-publish-natives.yml b/.github/workflows/build-and-publish-natives.yml similarity index 85% rename from .github/workflows/build-publish-natives.yml rename to .github/workflows/build-and-publish-natives.yml index 8850fb49..12e98107 100644 --- a/.github/workflows/build-publish-natives.yml +++ b/.github/workflows/build-and-publish-natives.yml @@ -6,7 +6,7 @@ on: paths: - 'NetCord.Natives/**' - '.github/workflows/build-natives.yml' - - '.github/workflows/publish-natives.yml' + - '.github/workflows/build-and-publish-natives.yml' tags: - "[0-9]+.[0-9]+.[0-9]+" - "[0-9]+.[0-9]+.[0-9]+-*" @@ -21,7 +21,7 @@ jobs: steps: - name: Download All NuGet Package Artifacts - uses: actions/download-artifact@v8.0.1 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: artifacts/pkgs pattern: NetCord.Natives.*.packages diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index 6cada1d3..c169b1be 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -15,18 +15,6 @@ on: jobs: build-natives: - runs-on: ${{ matrix.runs-on }} - env: - CI: true - VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite - VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads - VcpkgOSTarget: ${{ matrix.vcpkg-os-target }} - VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }} - Configuration: Release - RuntimeIdentifier: ${{ matrix.rid }} - DotnetVerbose: minimal - GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }} - strategy: fail-fast: false matrix: @@ -35,36 +23,55 @@ jobs: runs-on: windows-latest vcpkg-os-target: windows vcpkg-platform-target: x64 + run-prefix: '' - rid: win-arm64 runs-on: windows-11-arm vcpkg-os-target: windows vcpkg-platform-target: arm64 + run-prefix: '' - rid: osx-x64 runs-on: macos-15-intel vcpkg-os-target: osx vcpkg-platform-target: x64 + run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: osx-arm64 runs-on: macos-15 vcpkg-os-target: osx vcpkg-platform-target: arm64 + run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: linux-x64 runs-on: ubuntu-latest vcpkg-os-target: linux vcpkg-platform-target: x64 + run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: linux-arm64 runs-on: ubuntu-24.04-arm vcpkg-os-target: linux vcpkg-platform-target: arm64 + run-prefix: nix develop .#natives -c bash -eo pipefail -c + + runs-on: ${{ matrix.runs-on }} + env: + CI: true + VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite + VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads + VcpkgOSTarget: ${{ matrix.vcpkg-os-target }} + VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }} + RUN_PREFIX: ${{ matrix.run-prefix }} + Configuration: Release + RuntimeIdentifier: ${{ matrix.rid }} + DotnetVerbose: minimal + GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }} steps: - name: Checkout - uses: actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 filter: tree:0 - name: Restore vcpkg cache - uses: actions/cache/restore@v5.0.5 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | .vcpkg-cache @@ -78,52 +85,79 @@ jobs: uses: ./.github/actions/setup-vcpkg - name: Setup .NET Core SDK - uses: actions/setup-dotnet@v5.2.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: global-json-file: global.json - - name: Install native build tools (macOS) - if: runner.os == 'macOS' - shell: bash - run: | - brew update - for pkg in autoconf automake libtool; do - brew list $pkg &>/dev/null || brew install $pkg - done + - name: Install Nix + if: runner.os != 'Windows' + uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 + + - name: Setup dev environment + if: runner.os != 'Windows' + shell: pwsh + run: 'true' - name: Restore shell: pwsh run: | + $command = @' dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }} + '@ + + if ($env:RUN_PREFIX) { + Invoke-Expression "$env:RUN_PREFIX `"$command`"" + } + else { + Invoke-Expression $command + } - name: Build natives projects for ${{ matrix.rid }} shell: pwsh - run: > # Building tests will build dependencies including the native libraries - dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} - ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} - -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" - -p:GeneratePackageOnBuild=false -p:CI=false + run: | # Building tests will build dependencies including the native libraries + $command = @' + dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" -p:GeneratePackageOnBuild=false -p:CI=false + '@ + + if ($env:RUN_PREFIX) { + Invoke-Expression "$env:RUN_PREFIX `"$command`"" + } + else { + Invoke-Expression $command + } - name: Test natives outputs for ${{ matrix.rid }} shell: pwsh - run: > - dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} - ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} - --logger "console;verbosity=detailed" - --logger GitHubActions + run: | + $command = @' + dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} --logger "console;verbosity=detailed" --logger GitHubActions + '@ + + if ($env:RUN_PREFIX) { + Invoke-Expression "$env:RUN_PREFIX `"$command`"" + } + else { + Invoke-Expression $command + } - name: Pack NuGet Package for ${{ matrix.rid }} if: ${{ always() }} shell: pwsh - run: > - dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} - ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} - -o NetCord.Natives/bin/${{ matrix.rid }} - -p:CI=false + run: | + $command = @' + dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} -o NetCord.Natives/bin/${{ matrix.rid }} -p:CI=false + '@ + + if ($env:RUN_PREFIX) { + Invoke-Expression "$env:RUN_PREFIX `"$command`"" + } + else { + Invoke-Expression $command + } - name: Upload Binary Logs if: ${{ env.GenerateBinLog == 'true' && always() }} - uses: actions/upload-artifact@v4.6.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: ${{ matrix.rid }}-binlogs path: | @@ -131,7 +165,7 @@ jobs: - name: Upload NuGet Package Artifact if: ${{ always() }} - uses: actions/upload-artifact@v7.0.1 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: NetCord.Natives.${{ matrix.rid }}.packages path: | @@ -140,7 +174,7 @@ jobs: - name: Save vcpkg cache if: ${{ always() }} - uses: actions/cache/save@v5.0.5 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | .vcpkg-cache diff --git a/Documentation/guides/basic-concepts/installing-native-dependencies.md b/Documentation/guides/basic-concepts/installing-native-dependencies.md index c6791906..beaa9416 100644 --- a/Documentation/guides/basic-concepts/installing-native-dependencies.md +++ b/Documentation/guides/basic-concepts/installing-native-dependencies.md @@ -5,7 +5,11 @@ NetCord relies on several native libraries for high-performance audio processing ## Native Dependencies Context - **Libdave**: Essential for voice connection interactions. -- **Libsodium**: Used for encryption. While NetCord defaults to native AES-GCM (which does not require Libsodium), Libsodium is a highly recommended production dependency. It acts as a fallback for the XChaCha20-Poly1305 encryption mode, ensuring your bot remains compatible if Discord switches to this mode for your connection. +- **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: + - **Server-side limitation**: When connecting to a voice channel, Discord assigns you to a voice server. Depending on the server and region, it may or may not support AES-GCM. All voice servers support XChaCha20-Poly1305, so if AES-GCM is unavailable on the server you're assigned to, Libsodium is required to use XChaCha20-Poly1305 as a fallback. + - **Hardware limitation**: If your hardware doesn't support AES-GCM (rare but possible on older CPUs), Libsodium is required to provide the XChaCha20-Poly1305 fallback encryption. + + Without Libsodium, your bot will fail to connect to voice channels if either of these conditions occur. - **Opus**: A versatile audio codec required for any classes in NetCord prefixed with `Opus` (e.g., audio encoding/decoding). - **Zstd**: Used for efficient payload compression. @@ -16,14 +20,14 @@ NetCord distributes these dependencies as per-RID (Runtime Identifier) packages. ### Supported Platforms Packages are available for: -| Platform | RID | NativeAOT Support |
Size
![Storage Requirement](https://img.shields.io/badge/Runtime-Package-blue)
| +| Platform | RID | NativeAOT Support | NuGet Package | |----------|-----|-------------------------|-----------| -| Windows x64 | `win-x64` | βœ“ (Static CRT /MT) | ![Windows x64](https://img.shields.io/badge/6_MB-42_MB_(176_MB)-blue) | -| Windows ARM64 | `win-arm64` | βœ“ (Static CRT /MT) | ![Windows ARM64](https://img.shields.io/badge/6_MB-41_MB_(183_MB)-blue) | -| Linux x64 | `linux-x64` | βœ“ (Dynamic CRT) | ![Linux x64](https://img.shields.io/badge/10_MB-9_MB_(28_MB)-blue) | -| Linux ARM64 | `linux-arm64` | βœ“ (Dynamic CRT) | ![Linux ARM64](https://img.shields.io/badge/10_MB-8_MB_(26_MB)-blue) | -| β“˜ macOS x64 | `osx-x64` | βœ“ (Dynamic CRT) | ![macOS x64](https://img.shields.io/badge/15_MB-11_MB_(28_MB)-blue) | -| β“˜ macOS ARM64 | `osx-arm64` | βœ“ (Dynamic CRT) | ![macOS ARM64](https://img.shields.io/badge/13_MB-10_MB_(25_MB)-blue) | +| Windows x64 | `win-x64` | βœ“ (Static CRT /MT) | [![NetCord.Natives.win-x64](https://img.shields.io/nuget/v/NetCord.Natives.win-x64?label=NetCord.Natives.win-x64)](https://www.nuget.org/packages/NetCord.Natives.win-x64) | +| Windows ARM64 | `win-arm64` | βœ“ (Static CRT /MT) | [![NetCord.Natives.win-arm64](https://img.shields.io/nuget/v/NetCord.Natives.win-arm64?label=NetCord.Natives.win-arm64)](https://www.nuget.org/packages/NetCord.Natives.win-arm64) | +| Linux x64 | `linux-x64` | βœ“ (Dynamic CRT) | [![NetCord.Natives.linux-x64](https://img.shields.io/nuget/v/NetCord.Natives.linux-x64?label=NetCord.Natives.linux-x64)](https://www.nuget.org/packages/NetCord.Natives.linux-x64) | +| Linux ARM64 | `linux-arm64` | βœ“ (Dynamic CRT) | [![NetCord.Natives.linux-arm64](https://img.shields.io/nuget/v/NetCord.Natives.linux-arm64?label=NetCord.Natives.linux-arm64)](https://www.nuget.org/packages/NetCord.Natives.linux-arm64) | +| β“˜ macOS x64 | `osx-x64` | βœ“ (Dynamic CRT) | [![NetCord.Natives.osx-x64](https://img.shields.io/nuget/v/NetCord.Natives.osx-x64?label=NetCord.Natives.osx-x64)](https://www.nuget.org/packages/NetCord.Natives.osx-x64) | +| β“˜ macOS ARM64 | `osx-arm64` | βœ“ (Dynamic CRT) | [![NetCord.Natives.osx-arm64](https://img.shields.io/nuget/v/NetCord.Natives.osx-arm64?label=NetCord.Natives.osx-arm64)](https://www.nuget.org/packages/NetCord.Natives.osx-arm64) | β“˜ Currently, the macOS packages are built and published, but functions verification tests are skipped due to limitations with `dyld`. They are still expected to work correctly, but we recommend testing on macOS before production use. diff --git a/NetCord.Natives/NetCord.Natives.csproj b/NetCord.Natives/NetCord.Natives.csproj index a13b761d..cf6e4f23 100644 --- a/NetCord.Natives/NetCord.Natives.csproj +++ b/NetCord.Natives/NetCord.Natives.csproj @@ -119,7 +119,7 @@ - + diff --git a/NetCord.Natives/NetCord.Natives.props b/NetCord.Natives/NetCord.Natives.props index c1b6ee94..7060b8ea 100644 --- a/NetCord.Natives/NetCord.Natives.props +++ b/NetCord.Natives/NetCord.Natives.props @@ -1,4 +1,4 @@ - + + <_NetCordStaticLink Include="libsodium;sodium" Condition="'%(DirectPInvoke.Identity)' == 'libsodium'" /> diff --git a/NetCord.Natives/vcpkg-non-windows.targets b/NetCord.Natives/vcpkg-non-windows.targets index 134e697a..66778834 100644 --- a/NetCord.Natives/vcpkg-non-windows.targets +++ b/NetCord.Natives/vcpkg-non-windows.targets @@ -1,4 +1,4 @@ - + <_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgManifestFileLocation)"/> diff --git a/README.md b/README.md index cdbb638f..efd74ac6 100644 --- a/README.md +++ b/README.md @@ -32,7 +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 binaries dependencies. | +| 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 diff --git a/Resources/NuGet/README.md b/Resources/NuGet/README.md index d7babe22..617844cf 100644 --- a/Resources/NuGet/README.md +++ b/Resources/NuGet/README.md @@ -25,7 +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](https://www.nuget.org/packages/NetCord.Natives)** | Provides pre-built native binaries dependencies. | +| 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 diff --git a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj index d06d6424..11eff813 100644 --- a/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj +++ b/Tests/NetCord.Natives.Tests/Assets/NativeAotApp/NativeAotApp.csproj @@ -10,8 +10,6 @@ true true true - false - $(NoWarn);IL2075;IL2026 ..\..\..\..\NetCord.Natives
@@ -21,8 +19,10 @@ - - + + + + diff --git a/Tests/NetCord.Natives.Tests/NativeProbes.cs b/Tests/NetCord.Natives.Tests/NativeProbes.cs index 14338f93..4a03b6d2 100644 --- a/Tests/NetCord.Natives.Tests/NativeProbes.cs +++ b/Tests/NetCord.Natives.Tests/NativeProbes.cs @@ -23,7 +23,7 @@ internal static IReadOnlyList GetMissingLibraryImports(string libName, s var libHandle = GetLoadedNativeModuleHandle(libName); var missingExports = new List(); - var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.NonPublic) + var methods = typeWithImports!.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .Select(m => new { MethodName = m.Name, diff --git a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs index 8de10c24..ec112fbc 100644 --- a/Tests/NetCord.Natives.Tests/NativesBuildTests.cs +++ b/Tests/NetCord.Natives.Tests/NativesBuildTests.cs @@ -95,8 +95,6 @@ public void NativeAotStaticLinking(string libName) getRunCmd.StartInfo.ArgumentList.Add("-getProperty:PublishDir"); getRunCmd.StartInfo.ArgumentList.Add("--no-restore"); - getRunCmd.StartInfo.ArgumentList.Add("--bl"); - string? runCmdOutput = null; getRunCmd.StartInfo.WorkingDirectory = projectDirectory; diff --git a/flake.nix b/flake.nix index f9954b91..7a6c133e 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,14 @@ DOTNET_ROOT = dotnetRoot; }; + natives = pkgs.mkShell { + packages = [ + pkgs.autoconf + pkgs.automake + pkgs.libtool + ]; + }; + docs = pkgs.mkShell { packages = [ docfx From db1bc79b4d25693873b2e463bb54e3afbe72a9a2 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Wed, 27 May 2026 02:02:36 +0900 Subject: [PATCH 13/16] Revert to not using nix for building the natives, as it causes more issues than it solves (build tools & dependency pinning, which should already be handled by vcpkg). We can revisit this in the future if we find a better way to use nix for this purpose. * re-order workflow properties to be more logical and easier to read. This reverts commit e62276d6b10693fd3da6be1ad1bb094206181ef3. --- .github/workflows/build-natives.yml | 75 +++++++---------------------- 1 file changed, 18 insertions(+), 57 deletions(-) diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives.yml index c169b1be..83942d72 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives.yml @@ -23,32 +23,26 @@ jobs: runs-on: windows-latest vcpkg-os-target: windows vcpkg-platform-target: x64 - run-prefix: '' - rid: win-arm64 runs-on: windows-11-arm vcpkg-os-target: windows vcpkg-platform-target: arm64 - run-prefix: '' - rid: osx-x64 runs-on: macos-15-intel vcpkg-os-target: osx vcpkg-platform-target: x64 - run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: osx-arm64 runs-on: macos-15 vcpkg-os-target: osx vcpkg-platform-target: arm64 - run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: linux-x64 runs-on: ubuntu-latest vcpkg-os-target: linux vcpkg-platform-target: x64 - run-prefix: nix develop .#natives -c bash -eo pipefail -c - rid: linux-arm64 runs-on: ubuntu-24.04-arm vcpkg-os-target: linux vcpkg-platform-target: arm64 - run-prefix: nix develop .#natives -c bash -eo pipefail -c runs-on: ${{ matrix.runs-on }} env: @@ -57,7 +51,6 @@ jobs: VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads VcpkgOSTarget: ${{ matrix.vcpkg-os-target }} VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }} - RUN_PREFIX: ${{ matrix.run-prefix }} Configuration: Release RuntimeIdentifier: ${{ matrix.rid }} DotnetVerbose: minimal @@ -89,71 +82,39 @@ jobs: with: global-json-file: global.json - - name: Install Nix - if: runner.os != 'Windows' - uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 - - - name: Setup dev environment - if: runner.os != 'Windows' - shell: pwsh - run: 'true' + # - name: Install Nix + # if: runner.os != 'Windows' + # uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 - name: Restore shell: pwsh run: | - $command = @' dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }} - '@ - - if ($env:RUN_PREFIX) { - Invoke-Expression "$env:RUN_PREFIX `"$command`"" - } - else { - Invoke-Expression $command - } - name: Build natives projects for ${{ matrix.rid }} shell: pwsh - run: | # Building tests will build dependencies including the native libraries - $command = @' - dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" -p:GeneratePackageOnBuild=false -p:CI=false - '@ - - if ($env:RUN_PREFIX) { - Invoke-Expression "$env:RUN_PREFIX `"$command`"" - } - else { - Invoke-Expression $command - } + run: > # Building tests will build dependencies including the native libraries + dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} + -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" + -p:GeneratePackageOnBuild=false -p:CI=false - name: Test natives outputs for ${{ matrix.rid }} shell: pwsh - run: | - $command = @' - dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} --logger "console;verbosity=detailed" --logger GitHubActions - '@ - - if ($env:RUN_PREFIX) { - Invoke-Expression "$env:RUN_PREFIX `"$command`"" - } - else { - Invoke-Expression $command - } + run: > + dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} + --logger "console;verbosity=detailed" + --logger GitHubActions - name: Pack NuGet Package for ${{ matrix.rid }} if: ${{ always() }} shell: pwsh - run: | - $command = @' - dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} -o NetCord.Natives/bin/${{ matrix.rid }} -p:CI=false - '@ - - if ($env:RUN_PREFIX) { - Invoke-Expression "$env:RUN_PREFIX `"$command`"" - } - else { - Invoke-Expression $command - } + run: > + dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} + -o NetCord.Natives/bin/${{ matrix.rid }} + -p:CI=false - name: Upload Binary Logs if: ${{ env.GenerateBinLog == 'true' && always() }} From fac897f0a850accdd979ac7f79bb2dddcb6bbc31 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Sun, 31 May 2026 00:21:43 +0900 Subject: [PATCH 14/16] separate nix workflow & fix warn-no-error --- .github/actions/setup-vcpkg/action.yml | 43 ----- .../workflows/build-and-publish-natives.yml | 12 +- .github/workflows/build-and-publish.yml | 6 +- .github/workflows/build-natives-nix.yml | 148 ++++++++++++++++++ ...-natives.yml => build-natives-windows.yml} | 41 ++--- .../natives-ports/mlspp/portfile.cmake | 1 + 6 files changed, 174 insertions(+), 77 deletions(-) delete mode 100644 .github/actions/setup-vcpkg/action.yml create mode 100644 .github/workflows/build-natives-nix.yml rename .github/workflows/{build-natives.yml => build-natives-windows.yml} (80%) diff --git a/.github/actions/setup-vcpkg/action.yml b/.github/actions/setup-vcpkg/action.yml deleted file mode 100644 index 58416aea..00000000 --- a/.github/actions/setup-vcpkg/action.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Setup vcpkg -description: Setup vcpkg with fallback to submodule checkout - -runs: - using: composite - steps: - - name: Resolve or checkout vcpkg - shell: pwsh - run: | - # Ensure vcpkg cache and downloads directories exist - New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null - New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null - - $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT - if (-not $vcpkgRoot) { - $vcpkgCommand = Get-Command vcpkg -ErrorAction SilentlyContinue - if ($vcpkgCommand) { - $vcpkgRoot = Split-Path -Parent $vcpkgCommand.Source - } - } - - if (-not $vcpkgRoot -or -not (Test-Path $vcpkgRoot)) { - Write-Host "vcpkg not found in runner image, checking out from submodule..." - git config --file .gitmodules --get-regexp path | while-object { $_.Split()[-1] | where-object { $_ -match 'vcpkg' } } | ForEach-Object { - git submodule update --init --recursive $_ - } - $vcpkgRoot = Join-Path $env:GITHUB_WORKSPACE "vcpkg" - if (-not (Test-Path $vcpkgRoot)) { - Write-Error "vcpkg submodule not found and vcpkg executable not available" - exit 1 - } - } - - if (Test-Path $vcpkgRoot) { - Write-Host "Bootstrapping vcpkg from: $vcpkgRoot" - if ($IsWindows) { - & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics - } else { - & "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics - } - } - - "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 diff --git a/.github/workflows/build-and-publish-natives.yml b/.github/workflows/build-and-publish-natives.yml index 12e98107..a47964a5 100644 --- a/.github/workflows/build-and-publish-natives.yml +++ b/.github/workflows/build-and-publish-natives.yml @@ -5,18 +5,22 @@ on: push: paths: - 'NetCord.Natives/**' - - '.github/workflows/build-natives.yml' + - '.github/workflows/build-natives-nix.yml' + - '.github/workflows/build-natives-windows.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 + build-natives-nix: + uses: ./.github/workflows/build-natives-nix.yml + + build-natives-windows: + uses: ./.github/workflows/build-natives-windows.yml publish: - needs: [build-natives] + needs: [build-natives-nix, build-natives-windows] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 1bdd8c0f..e0ebef8d 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -16,14 +16,14 @@ jobs: steps: - name: Download Build Artifacts - uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: NuGet Packages path: artifacts/pkgs merge-multiple: true - name: Download Documentation Artifacts - uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + uses: actions/download-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Documentation Artifacts path: artifacts/docs @@ -44,7 +44,7 @@ jobs: 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 + uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0 with: username: ${{ secrets.SSH_USERNAME }} host: ${{ secrets.SSH_HOST }} diff --git a/.github/workflows/build-natives-nix.yml b/.github/workflows/build-natives-nix.yml new file mode 100644 index 00000000..4dcfd87f --- /dev/null +++ b/.github/workflows/build-natives-nix.yml @@ -0,0 +1,148 @@ +name: Build NetCord.Natives (Linux/MacOS, Nix) + +on: + workflow_call: + workflow_dispatch: + inputs: + GenerateBinLog: + type: boolean + default: false + push: + paths: + - 'NetCord.Natives/**' + - 'Tests/NetCord.Natives.Tests/**' + - '.github/workflows/build-natives-nix.yml' + +jobs: + build-natives-nix: + strategy: + fail-fast: false + matrix: + include: + - rid: osx-x64 + runs-on: macos-15-intel + vcpkg-os-target: osx + vcpkg-platform-target: x64 + - rid: osx-arm64 + runs-on: macos-15 + vcpkg-os-target: osx + vcpkg-platform-target: arm64 + - rid: linux-x64 + runs-on: ubuntu-latest + vcpkg-os-target: linux + vcpkg-platform-target: x64 + - rid: linux-arm64 + runs-on: ubuntu-24.04-arm + vcpkg-os-target: linux + vcpkg-platform-target: arm64 + + runs-on: ${{ matrix.runs-on }} + env: + CI: true + VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite + VCPKG_DOWNLOADS: ${{ github.workspace }}/.vcpkg-downloads + VcpkgOSTarget: ${{ matrix.vcpkg-os-target }} + VcpkgPlatformTarget: ${{ matrix.vcpkg-platform-target }} + Configuration: Release + RuntimeIdentifier: ${{ matrix.rid }} + DotnetVerbose: minimal + GenerateBinLog: ${{ github.event.inputs.GenerateBinLog || inputs.GenerateBinLog || false }} + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + filter: tree:0 + + - name: Restore vcpkg cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: | + .vcpkg-cache + .vcpkg-downloads + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json', 'NetCord.Natives/natives-ports/**') }} + restore-keys: | + vcpkg-${{ runner.os }}-${{ matrix.rid }}- + vcpkg-${{ runner.os }}- + + - name: Install Nix + uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 + + - name: Setup vcpkg (non-Windows, Nix) + shell: bash + run: | + cat > bootstrap-vcpkg.sh <<'EOF' + #!/usr/bin/env bash + set -euo pipefail + mkdir -p "${VCPKG_BINARY_SOURCES#*,}" + mkdir -p "${VCPKG_DOWNLOADS}" + vcpkgRoot="${GITHUB_WORKSPACE}/NetCord.Natives/vcpkg" + echo "Bootstrapping vcpkg from: $vcpkgRoot" + "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics + echo "VCPKG_ROOT=$vcpkgRoot" >> "$GITHUB_ENV" + EOF + + chmod +x bootstrap-vcpkg.sh + nix-shell --run ./bootstrap-vcpkg.sh + rm -f bootstrap-vcpkg.sh + + - name: Setup dev shell + shell: &dev-shell 'nix develop -c bash -eo pipefail {0}' + run: 'true' + + - name: Restore + shell: *dev-shell + run: | + dotnet restore Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:restore.binlog' || '' }} + + - name: Build natives projects for ${{ matrix.rid }} + shell: *dev-shell + run: > + dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} + -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" + -p:GeneratePackageOnBuild=false -p:CI=false + + - name: Test natives outputs for ${{ matrix.rid }} + shell: *dev-shell + run: > + dotnet test Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:test.binlog' || '' }} + --logger "console;verbosity=detailed" + --logger GitHubActions + + - name: Pack NuGet Package for ${{ matrix.rid }} + if: ${{ always() }} + shell: *dev-shell + run: > + dotnet pack NetCord.Natives/NetCord.Natives.csproj --no-restore --no-build -v ${{ env.DotnetVerbose }} + ${{ env.GenerateBinLog == 'true' && '-bl:pack.binlog' || '' }} + -o NetCord.Natives/bin/${{ matrix.rid }} + -p:CI=false + + - name: Upload Binary Logs + if: ${{ env.GenerateBinLog == 'true' && always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: ${{ matrix.rid }}-binlogs + path: | + *.binlog + + - name: Upload NuGet Package Artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: NetCord.Natives.${{ matrix.rid }}.packages + path: | + NetCord.Natives/bin/${{ matrix.rid }}/*.nupkg + NetCord.Natives/bin/${{ matrix.rid }}/*.snupkg + + - name: Save vcpkg cache + if: ${{ always() }} + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: | + .vcpkg-cache + .vcpkg-downloads + key: vcpkg-${{ runner.os }}-${{ matrix.rid }}-${{ hashFiles('NetCord.Natives/vcpkg.json', 'NetCord.Natives/natives-ports/**') }} diff --git a/.github/workflows/build-natives.yml b/.github/workflows/build-natives-windows.yml similarity index 80% rename from .github/workflows/build-natives.yml rename to .github/workflows/build-natives-windows.yml index 83942d72..a7c8fd29 100644 --- a/.github/workflows/build-natives.yml +++ b/.github/workflows/build-natives-windows.yml @@ -1,4 +1,4 @@ -name: Build NetCord.Natives +name: Build NetCord.Natives (Windows) on: workflow_call: @@ -11,10 +11,10 @@ on: paths: - 'NetCord.Natives/**' - 'Tests/NetCord.Natives.Tests/**' - - '.github/workflows/build-natives.yml' + - '.github/workflows/build-natives-windows.yml' jobs: - build-natives: + build-natives-windows: strategy: fail-fast: false matrix: @@ -27,22 +27,6 @@ jobs: runs-on: windows-11-arm vcpkg-os-target: windows vcpkg-platform-target: arm64 - - rid: osx-x64 - runs-on: macos-15-intel - vcpkg-os-target: osx - vcpkg-platform-target: x64 - - rid: osx-arm64 - runs-on: macos-15 - vcpkg-os-target: osx - vcpkg-platform-target: arm64 - - rid: linux-x64 - runs-on: ubuntu-latest - vcpkg-os-target: linux - vcpkg-platform-target: x64 - - rid: linux-arm64 - runs-on: ubuntu-24.04-arm - vcpkg-os-target: linux - vcpkg-platform-target: arm64 runs-on: ${{ matrix.runs-on }} env: @@ -74,18 +58,21 @@ jobs: vcpkg-${{ runner.os }}-${{ matrix.rid }}- vcpkg-${{ runner.os }}- - - name: Setup vcpkg - uses: ./.github/actions/setup-vcpkg + - name: Setup vcpkg (Windows) + shell: pwsh + run: | + New-Item -ItemType Directory -Path $env:VCPKG_BINARY_SOURCES.Split(',')[1] -Force | Out-Null + New-Item -ItemType Directory -Path $env:VCPKG_DOWNLOADS -Force | Out-Null + $vcpkgRoot = Join-Path $env:GITHUB_WORKSPACE "NetCord.Natives/vcpkg" + Write-Host "Bootstrapping vcpkg from: $vcpkgRoot" + & "$vcpkgRoot/bootstrap-vcpkg.bat" -disableMetrics + "VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - name: Setup .NET Core SDK uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: global-json-file: global.json - # - name: Install Nix - # if: runner.os != 'Windows' - # uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 - - name: Restore shell: pwsh run: | @@ -93,7 +80,7 @@ jobs: - name: Build natives projects for ${{ matrix.rid }} shell: pwsh - run: > # Building tests will build dependencies including the native libraries + run: > dotnet build Tests/NetCord.Natives.Tests/NetCord.Natives.Tests.csproj --no-restore -v ${{ env.DotnetVerbose }} ${{ env.GenerateBinLog == 'true' && '-bl:build.binlog' || '' }} -p:AppendNativeAotAppProps="RuntimeIdentifier=${{ env.RuntimeIdentifier }}" @@ -118,7 +105,7 @@ jobs: - name: Upload Binary Logs if: ${{ env.GenerateBinLog == 'true' && always() }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ matrix.rid }}-binlogs path: | diff --git a/NetCord.Natives/natives-ports/mlspp/portfile.cmake b/NetCord.Natives/natives-ports/mlspp/portfile.cmake index 2ca219e3..4e863f9f 100644 --- a/NetCord.Natives/natives-ports/mlspp/portfile.cmake +++ b/NetCord.Natives/natives-ports/mlspp/portfile.cmake @@ -19,6 +19,7 @@ vcpkg_cmake_configure( -DTESTING=OFF -DBUILD_TESTING=OFF -DMLS_CXX_NAMESPACE="mlspp" + -DCMAKE_CXX_FLAGS="-Wno-error" MAYBE_UNUSED_VARIABLES BUILD_TESTING ) From 990f54df5abd544644132855c25058a6fe986183 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Sun, 31 May 2026 00:44:12 +0900 Subject: [PATCH 15/16] fix checkout submodules --- .github/workflows/build-natives-nix.yml | 1 + .github/workflows/build-natives-windows.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build-natives-nix.yml b/.github/workflows/build-natives-nix.yml index 4dcfd87f..0647f3d7 100644 --- a/.github/workflows/build-natives-nix.yml +++ b/.github/workflows/build-natives-nix.yml @@ -54,6 +54,7 @@ jobs: with: fetch-depth: 0 filter: tree:0 + submodules: true - name: Restore vcpkg cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 diff --git a/.github/workflows/build-natives-windows.yml b/.github/workflows/build-natives-windows.yml index a7c8fd29..df5847fa 100644 --- a/.github/workflows/build-natives-windows.yml +++ b/.github/workflows/build-natives-windows.yml @@ -46,6 +46,7 @@ jobs: with: fetch-depth: 0 filter: tree:0 + submodules: true - name: Restore vcpkg cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 From e0b243115ae0346cf9e3eb046d10be5ead6e86d4 Mon Sep 17 00:00:00 2001 From: Haves Irfan <20160532+ha-ves@users.noreply.github.com> Date: Sun, 31 May 2026 00:50:29 +0900 Subject: [PATCH 16/16] [skip ci] rearrange nix & fix vcpkg --- .github/workflows/build-natives-nix.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-natives-nix.yml b/.github/workflows/build-natives-nix.yml index 0647f3d7..1e5a0bda 100644 --- a/.github/workflows/build-natives-nix.yml +++ b/.github/workflows/build-natives-nix.yml @@ -70,27 +70,19 @@ jobs: - name: Install Nix uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 + - name: Setup dev shell + shell: &dev-shell 'nix develop -c bash -eo pipefail {0}' + run: 'true' + - name: Setup vcpkg (non-Windows, Nix) - shell: bash + shell: *dev-shell run: | - cat > bootstrap-vcpkg.sh <<'EOF' - #!/usr/bin/env bash - set -euo pipefail mkdir -p "${VCPKG_BINARY_SOURCES#*,}" mkdir -p "${VCPKG_DOWNLOADS}" vcpkgRoot="${GITHUB_WORKSPACE}/NetCord.Natives/vcpkg" echo "Bootstrapping vcpkg from: $vcpkgRoot" "$vcpkgRoot/bootstrap-vcpkg.sh" -disableMetrics echo "VCPKG_ROOT=$vcpkgRoot" >> "$GITHUB_ENV" - EOF - - chmod +x bootstrap-vcpkg.sh - nix-shell --run ./bootstrap-vcpkg.sh - rm -f bootstrap-vcpkg.sh - - - name: Setup dev shell - shell: &dev-shell 'nix develop -c bash -eo pipefail {0}' - run: 'true' - name: Restore shell: *dev-shell