diff --git a/.github/workflows/build_latest.yml b/.github/workflows/build_latest.yml index 4025f484..1935f800 100644 --- a/.github/workflows/build_latest.yml +++ b/.github/workflows/build_latest.yml @@ -19,7 +19,7 @@ on: default: 'main' env: - DOTNET_SDK_VERSION: "9.0.306" + DOTNET_SDK_VERSION: "10.0.101" ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: @@ -62,7 +62,7 @@ jobs: with: dotnet-version: ${{ env.DOTNET_SDK_VERSION }} - - run: powershell -Command "(Get-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj) -replace '.*', 'net9.0-windows' | Set-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj" + - run: powershell -Command "(Get-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj) -replace '.*', 'net10.0-windows' | Set-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj" - run: dotnet add src/N_m3u8DL-RE/N_m3u8DL-RE.csproj package YY-Thunks --version 1.1.4 - run: dotnet add src/N_m3u8DL-RE/N_m3u8DL-RE.csproj package VC-LTL --version 5.1.1 - run: dotnet publish src/N_m3u8DL-RE -p:TargetPlatformMinVersion=6.0 -r win-x86 -c Release -o artifact-x86 @@ -117,82 +117,6 @@ jobs: name: win-arm64 path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_win-arm64_${{ needs.set-date.outputs.date }}.zip - build-linux-x64-arm64: - runs-on: ubuntu-latest - needs: set-date - - steps: - - uses: actions/checkout@v1 - with: - ref: ${{ github.event.inputs.ref }} - - - name: Build x64 in Ubuntu 18.04 container (for glibc 2.27 compatibility) - run: | - # 在 Ubuntu 18.04 容器中执行完整构建流程 - docker run --rm \ - -v "$PWD:/workspace" \ - -w /workspace \ - ubuntu:18.04 \ - bash -c " - set -e - - # 安装编译和运行依赖 - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y wget build-essential clang libicu-dev zlib1g libcurl4-openssl-dev libkrb5-dev - - # 下载并安装 .NET SDK - DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}' - DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\" - wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz - mkdir -p /opt/dotnet - tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet - export PATH=\"/opt/dotnet:\$PATH\" - - # 编译 Native AOT 输出到挂载的 artifact 目录 - dotnet publish src/N_m3u8DL-RE -r linux-x64 -c Release -o /workspace/artifact - " - - - name: Build arm64 in Ubuntu 18.04 container (for glibc 2.27 compatibility) - run: | - # 在 Ubuntu 18.04 容器中执行完整构建流程 - docker run --rm \ - -v "$PWD:/workspace" \ - -w /workspace \ - mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-arm64-20220312201346-b2c2436 \ - bash -c " - set -e - - # 下载并安装 .NET SDK - DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}' - DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\" - wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz - mkdir -p /opt/dotnet - tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet - export PATH=\"/opt/dotnet:\$PATH\" - - # 编译 Native AOT 输出到挂载的 artifact 目录 - dotnet publish src/N_m3u8DL-RE -r linux-arm64 -c Release -p:StripSymbols=true -p:CppCompilerAndLinker=clang-9 -p:SysRoot=/crossrootfs/arm64 -o /workspace/artifact-arm64 - " - - - name: Package [linux] - run: | - cd artifact - tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE - cd ../artifact-arm64 - tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE - - - name: Upload Artifact [linux-x64] - uses: actions/upload-artifact@v4 - with: - name: linux-x64 - path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz - - - name: Upload Artifact[linux-arm64] - uses: actions/upload-artifact@v4 - with: - name: linux-arm64 - path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz - build-android-bionic-x64-arm64: runs-on: windows-latest needs: set-date @@ -217,7 +141,7 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: ${{ env.DOTNET_SDK_VERSION }} - + - run: dotnet publish src/N_m3u8DL-RE -r linux-bionic-x64 -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true -o artifact - run: dotnet publish src/N_m3u8DL-RE -r linux-bionic-arm64 -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true -o artifact-arm64 @@ -240,59 +164,128 @@ jobs: name: android-bionic-arm64 path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_android-bionic-arm64_${{ needs.set-date.outputs.date }}.tar.gz - build-linux-musl-x64: + build-linux-x64: runs-on: ubuntu-latest needs: set-date - container: mcr.microsoft.com/dotnet/sdk:9.0-alpine-amd64 steps: - uses: actions/checkout@v1 with: ref: ${{ github.event.inputs.ref }} - - run: apk add clang build-base zlib-dev - - run: dotnet publish src/N_m3u8DL-RE -r linux-musl-x64 -c Release -o artifact -p:InvariantGlobalization=true + - name: Build x64 in alpine container + run: | + # 在 alpine 容器中执行完整构建流程 + docker run --rm \ + -v "$PWD:/workspace" \ + -w /workspace \ + alpine:3.21 \ + sh -c " + set -e + + # 安装编译和运行依赖 + apk add --no-cache bash wget tar clang build-base cmake icu-dev icu-data-full zlib-static openssl-dev openssl-libs-static + + # 下载并安装 .NET SDK + DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}' + DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-musl-x64.tar.gz\" + wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz + mkdir -p /opt/dotnet + tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet + export PATH=\"/opt/dotnet:\$PATH\" + + # 编译 Native AOT 输出到挂载的 artifact 目录 + dotnet publish src/N_m3u8DL-RE -r linux-musl-x64 -c Release -o /workspace/artifact + " - - name: Package [linux-musl-x64] + - name: Package [linux-x64] run: | cd artifact - tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE + tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE - - name: Upload Artifact [linux-musl-x64] + - name: Upload Artifact [linux-x64] uses: actions/upload-artifact@v4 with: - name: linux-musl-x64 - path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-x64_${{ needs.set-date.outputs.date }}.tar.gz + name: linux-x64 + path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz - build-linux-musl-arm64: + build-linux-arm64: runs-on: ubuntu-latest needs: set-date - container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-arm64-alpine steps: - uses: actions/checkout@v1 with: ref: ${{ github.event.inputs.ref }} - - name: Set up dotnet - uses: actions/setup-dotnet@v3 - with: - dotnet-version: ${{ env.DOTNET_SDK_VERSION }} - - - run: apt-get update - - run: apt-get install -y build-essential clang binutils-aarch64-linux-gnu - - run: dotnet publish src/N_m3u8DL-RE -r linux-musl-arm64 -c Release -o artifact -p:CppCompilerAndLinker=clang -p:SysRoot=/crossrootfs/arm64 -p:InvariantGlobalization=true + - name: Build arm64 in alpine container + run: | + # 在交叉编译环境容器中执行完整构建流程 + docker run --rm \ + -v "$PWD:/workspace" \ + -w /workspace \ + mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-arm64-alpine \ + bash -c " + set -e + + # 确保 Ubuntu 宿主环境有所有依赖 + apt-get update && apt-get install -y build-essential clang binutils-aarch64-linux-gnu + + # 动态获取 Alpine 最新 OpenSSL 版本号 + ALPINE_REPO='https://dl-cdn.alpinelinux.org/alpine/v3.21/main/aarch64' + echo \"Fetching latest OpenSSL version from Alpine...\" + # 自动抓取 openssl-dev 的完整文件名并解析版本号 + SSL_APK_NAME=\$(wget -qO- \$ALPINE_REPO/ | grep -o 'openssl-dev-[0-9.]\+-r[0-9]\+.apk' | head -n 1) + SSL_VER=\$(echo \$SSL_APK_NAME | sed 's/openssl-dev-//;s/.apk//') + echo \"Detected OpenSSL Version: \$SSL_VER\" + + # 下载并提取 ARM64 的 OpenSSL 静态库到 SysRoot + mkdir -p /tmp/ssl_setup && cd /tmp/ssl_setup + wget -q \$ALPINE_REPO/openssl-libs-static-\$SSL_VER.apk + wget -q \$ALPINE_REPO/openssl-dev-\$SSL_VER.apk + + # 解压到交叉编译系统的根目录 + for f in *.apk; do tar -xf \$f -C /crossrootfs/arm64; done + cd /workspace + + # 设置交叉编译环境变量 (强制 CMake 和编译器使用正确路径) + export CROSS_COMPILE_PREFIX=\"aarch64-alpine-linux-musl-\" + export CC=\"\${CROSS_COMPILE_PREFIX}clang\" + export CXX=\"\${CROSS_COMPILE_PREFIX}clang++\" + + # 告知 .NET 本地脚本去哪里找 OpenSSL 静态库 + export OPENSSL_ROOT_DIR=\"/crossrootfs/arm64/usr\" + export OPENSSL_USE_STATIC_LIBS=TRUE + + # 额外保险:设置 CFLAGS 让 CMake 内部探测更准确 + export CFLAGS=\"--sysroot=/crossrootfs/arm64 --target=aarch64-alpine-linux-musl\" + + # 下载并安装 .NET SDK + DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}' + DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\" + wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz + mkdir -p /opt/dotnet + tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet + export PATH=\"/opt/dotnet:\$PATH\" + + # 交叉编译 + dotnet publish src/N_m3u8DL-RE -r linux-musl-arm64 -c Release \ + -p:SysRoot=/crossrootfs/arm64 \ + -p:CppCompilerAndLinker=clang \ + -p:StripSymbols=true \ + -o /workspace/artifact + " - - name: Package [linux-musl-arm64] + - name: Package [linux-arm64] run: | cd artifact - tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE + tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE - - name: Upload Artifact [linux-musl-arm64] + - name: Upload Artifact [linux-x64] uses: actions/upload-artifact@v4 with: - name: linux-musl-arm64 - path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-arm64_${{ needs.set-date.outputs.date }}.tar.gz + name: linux-arm64 + path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz build-mac-x64-arm64: runs-on: macos-latest @@ -335,8 +328,8 @@ jobs: permissions: contents: write if: ${{ github.event.inputs.doRelease == 'true' }} - needs: [set-date,build-win-nt6_0-x86,build-win-x64-arm64,build-linux-x64-arm64,build-android-bionic-x64-arm64,build-linux-musl-x64,build-linux-musl-arm64,build-mac-x64-arm64] - + needs: [set-date,build-win-nt6_0-x86,build-win-x64-arm64,build-android-bionic-x64-arm64,build-linux-x64,build-linux-arm64,build-mac-x64-arm64] + steps: - name: Fetch artifacts uses: actions/download-artifact@v4 diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs index aa39dc66..fed7a1be 100644 --- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs +++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs @@ -15,7 +15,7 @@ namespace N_m3u8DL_RE.CommandLine; internal static partial class CommandInvoker { - public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20251029"; + public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20251228"; [GeneratedRegex("((best|worst)\\d*|all)")] private static partial Regex ForStrRegex(); @@ -686,9 +686,7 @@ private static MyOption GetOptions(ParseResult result) // 以用户选择语言为准优先 if (option.UILanguage != null) { - CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(option.UILanguage); - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(option.UILanguage); - Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(option.UILanguage); + CultureUtil.ChangeCurrentCultureName(option.UILanguage); } // 混流设置 diff --git a/src/N_m3u8DL-RE/Directory.Build.props b/src/N_m3u8DL-RE/Directory.Build.props index 0276d837..97dc8ef5 100644 --- a/src/N_m3u8DL-RE/Directory.Build.props +++ b/src/N_m3u8DL-RE/Directory.Build.props @@ -14,6 +14,20 @@ aarch64-linux-gnu-objcopy + + + + + + + + true + + true + + true + + diff --git a/src/N_m3u8DL-RE/Program.cs b/src/N_m3u8DL-RE/Program.cs index fc3ece1f..318211f1 100644 --- a/src/N_m3u8DL-RE/Program.cs +++ b/src/N_m3u8DL-RE/Program.cs @@ -36,10 +36,7 @@ static async Task Main(string[] args) ServicePointManager.DefaultConnectionLimit = 1024; try { Console.CursorVisible = true; } catch { } - string loc = ResString.CurrentLoc; - string currLoc = Thread.CurrentThread.CurrentUICulture.Name; - if (currLoc is "zh-CN" or "zh-SG") loc = "zh-CN"; - else if (currLoc.StartsWith("zh-")) loc = "zh-TW"; + string loc = CultureUtil.GetCurrentCultureName(); // 处理用户-h等请求 var index = -1; @@ -51,16 +48,7 @@ static async Task Main(string[] args) ResString.CurrentLoc = loc; - try - { - CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(loc); - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(loc); - Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(loc); - } - catch - { - // Culture not work on NT6.0, so catch the exception - } + CultureUtil.ChangeCurrentCultureName(loc); await CommandInvoker.InvokeArgs(args, DoWorkAsync); } diff --git a/src/N_m3u8DL-RE/Util/CultureUtil.cs b/src/N_m3u8DL-RE/Util/CultureUtil.cs new file mode 100644 index 00000000..c59ac9a1 --- /dev/null +++ b/src/N_m3u8DL-RE/Util/CultureUtil.cs @@ -0,0 +1,45 @@ +using N_m3u8DL_RE.Common.Resource; + +namespace N_m3u8DL_RE.Util; + +public static class CultureUtil +{ + public static string GetCurrentCultureName() + { + string loc = ResString.CurrentLoc; + string currLoc = Thread.CurrentThread.CurrentUICulture.Name; + + if (string.IsNullOrEmpty(currLoc)) + currLoc = GetCurrentCultureNameFromEnvironment(); + + if (currLoc is "zh-CN" or "zh-SG") + loc = "zh-CN"; + else if (currLoc.StartsWith("zh-")) + loc = "zh-TW"; + + return loc; + } + + public static void ChangeCurrentCultureName(string newName) + { + try + { + System.Globalization.CultureInfo.DefaultThreadCurrentCulture = new System.Globalization.CultureInfo(newName); + Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(newName); + Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(newName); + } + catch (Exception) + { + // Culture not work on NT6.0, so catch the exception + } + } + + private static string GetCurrentCultureNameFromEnvironment() + { + // 尝试读取 LC_ALL, LANG + string langEnv = Environment.GetEnvironmentVariable("LC_ALL") + ?? Environment.GetEnvironmentVariable("LANG") + ?? ResString.CurrentLoc; + return langEnv.Split('.')[0].Replace('_', '-'); + } +} \ No newline at end of file