Skip to content

Commit 6bdf28b

Browse files
committed
Linux x64/arm64实现静态编译
1 parent 17d697b commit 6bdf28b

File tree

5 files changed

+159
-121
lines changed

5 files changed

+159
-121
lines changed

.github/workflows/build_latest.yml

Lines changed: 96 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ on:
1919
default: 'main'
2020

2121
env:
22-
DOTNET_SDK_VERSION: "9.0.306"
22+
DOTNET_SDK_VERSION: "10.0.101"
2323
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
2424

2525
jobs:
@@ -62,7 +62,7 @@ jobs:
6262
with:
6363
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
6464

65-
- run: powershell -Command "(Get-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj) -replace '<TargetFramework>.*</TargetFramework>', '<TargetFramework>net9.0-windows</TargetFramework>' | Set-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj"
65+
- run: powershell -Command "(Get-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj) -replace '<TargetFramework>.*</TargetFramework>', '<TargetFramework>net10.0-windows</TargetFramework>' | Set-Content src/N_m3u8DL-RE/N_m3u8DL-RE.csproj"
6666
- run: dotnet add src/N_m3u8DL-RE/N_m3u8DL-RE.csproj package YY-Thunks --version 1.1.4
6767
- run: dotnet add src/N_m3u8DL-RE/N_m3u8DL-RE.csproj package VC-LTL --version 5.1.1
6868
- run: dotnet publish src/N_m3u8DL-RE -p:TargetPlatformMinVersion=6.0 -r win-x86 -c Release -o artifact-x86
@@ -117,82 +117,6 @@ jobs:
117117
name: win-arm64
118118
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_win-arm64_${{ needs.set-date.outputs.date }}.zip
119119

120-
build-linux-x64-arm64:
121-
runs-on: ubuntu-latest
122-
needs: set-date
123-
124-
steps:
125-
- uses: actions/checkout@v1
126-
with:
127-
ref: ${{ github.event.inputs.ref }}
128-
129-
- name: Build x64 in Ubuntu 18.04 container (for glibc 2.27 compatibility)
130-
run: |
131-
# 在 Ubuntu 18.04 容器中执行完整构建流程
132-
docker run --rm \
133-
-v "$PWD:/workspace" \
134-
-w /workspace \
135-
ubuntu:18.04 \
136-
bash -c "
137-
set -e
138-
139-
# 安装编译和运行依赖
140-
apt-get update
141-
DEBIAN_FRONTEND=noninteractive apt-get install -y wget build-essential clang libicu-dev zlib1g libcurl4-openssl-dev libkrb5-dev
142-
143-
# 下载并安装 .NET SDK
144-
DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}'
145-
DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\"
146-
wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz
147-
mkdir -p /opt/dotnet
148-
tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet
149-
export PATH=\"/opt/dotnet:\$PATH\"
150-
151-
# 编译 Native AOT 输出到挂载的 artifact 目录
152-
dotnet publish src/N_m3u8DL-RE -r linux-x64 -c Release -o /workspace/artifact
153-
"
154-
155-
- name: Build arm64 in Ubuntu 18.04 container (for glibc 2.27 compatibility)
156-
run: |
157-
# 在 Ubuntu 18.04 容器中执行完整构建流程
158-
docker run --rm \
159-
-v "$PWD:/workspace" \
160-
-w /workspace \
161-
mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-arm64-20220312201346-b2c2436 \
162-
bash -c "
163-
set -e
164-
165-
# 下载并安装 .NET SDK
166-
DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}'
167-
DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\"
168-
wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz
169-
mkdir -p /opt/dotnet
170-
tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet
171-
export PATH=\"/opt/dotnet:\$PATH\"
172-
173-
# 编译 Native AOT 输出到挂载的 artifact 目录
174-
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
175-
"
176-
177-
- name: Package [linux]
178-
run: |
179-
cd artifact
180-
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
181-
cd ../artifact-arm64
182-
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
183-
184-
- name: Upload Artifact [linux-x64]
185-
uses: actions/upload-artifact@v4
186-
with:
187-
name: linux-x64
188-
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz
189-
190-
- name: Upload Artifact[linux-arm64]
191-
uses: actions/upload-artifact@v4
192-
with:
193-
name: linux-arm64
194-
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz
195-
196120
build-android-bionic-x64-arm64:
197121
runs-on: windows-latest
198122
needs: set-date
@@ -217,7 +141,7 @@ jobs:
217141
uses: actions/setup-dotnet@v3
218142
with:
219143
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
220-
144+
221145
- run: dotnet publish src/N_m3u8DL-RE -r linux-bionic-x64 -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true -o artifact
222146
- run: dotnet publish src/N_m3u8DL-RE -r linux-bionic-arm64 -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true -o artifact-arm64
223147

@@ -243,56 +167,125 @@ jobs:
243167
build-linux-musl-x64:
244168
runs-on: ubuntu-latest
245169
needs: set-date
246-
container: mcr.microsoft.com/dotnet/sdk:9.0-alpine-amd64
247170

248171
steps:
249172
- uses: actions/checkout@v1
250173
with:
251174
ref: ${{ github.event.inputs.ref }}
252175

253-
- run: apk add clang build-base zlib-dev
254-
- run: dotnet publish src/N_m3u8DL-RE -r linux-musl-x64 -c Release -o artifact -p:InvariantGlobalization=true
176+
- name: Build x64 in alpine container
177+
run: |
178+
# 在 alpine 容器中执行完整构建流程
179+
docker run --rm \
180+
-v "$PWD:/workspace" \
181+
-w /workspace \
182+
alpine:3.21 \
183+
sh -c "
184+
set -e
185+
186+
# 安装编译和运行依赖
187+
apk add --no-cache bash wget tar clang build-base cmake icu-dev icu-data-full zlib-static openssl-dev openssl-libs-static
188+
189+
# 下载并安装 .NET SDK
190+
DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}'
191+
DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-musl-x64.tar.gz\"
192+
wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz
193+
mkdir -p /opt/dotnet
194+
tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet
195+
export PATH=\"/opt/dotnet:\$PATH\"
196+
197+
# 编译 Native AOT 输出到挂载的 artifact 目录
198+
dotnet publish src/N_m3u8DL-RE -r linux-musl-x64 -c Release -o /workspace/artifact
199+
"
255200
256-
- name: Package [linux-musl-x64]
201+
- name: Package [linux-x64]
257202
run: |
258203
cd artifact
259-
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
204+
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
260205
261-
- name: Upload Artifact [linux-musl-x64]
206+
- name: Upload Artifact [linux-x64]
262207
uses: actions/upload-artifact@v4
263208
with:
264-
name: linux-musl-x64
265-
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-x64_${{ needs.set-date.outputs.date }}.tar.gz
209+
name: linux-x64
210+
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-x64_${{ needs.set-date.outputs.date }}.tar.gz
266211
267212
build-linux-musl-arm64:
268213
runs-on: ubuntu-latest
269214
needs: set-date
270-
container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-arm64-alpine
271215
272216
steps:
273217
- uses: actions/checkout@v1
274218
with:
275219
ref: ${{ github.event.inputs.ref }}
276220
277-
- name: Set up dotnet
278-
uses: actions/setup-dotnet@v3
279-
with:
280-
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
281-
282-
- run: apt-get update
283-
- run: apt-get install -y build-essential clang binutils-aarch64-linux-gnu
284-
- 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
221+
- name: Build arm64 in alpine container
222+
run: |
223+
# 在交叉编译环境容器中执行完整构建流程
224+
docker run --rm \
225+
-v "$PWD:/workspace" \
226+
-w /workspace \
227+
mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-cross-arm64-alpine \
228+
bash -c "
229+
set -e
230+
231+
# 确保 Ubuntu 宿主环境有所有依赖
232+
apt-get update && apt-get install -y build-essential clang binutils-aarch64-linux-gnu
233+
234+
# 动态获取 Alpine 最新 OpenSSL 版本号
235+
ALPINE_REPO='https://dl-cdn.alpinelinux.org/alpine/v3.21/main/aarch64'
236+
echo \"Fetching latest OpenSSL version from Alpine...\"
237+
# 自动抓取 openssl-dev 的完整文件名并解析版本号
238+
SSL_APK_NAME=\$(wget -qO- \$ALPINE_REPO/ | grep -o 'openssl-dev-[0-9.]\+-r[0-9]\+.apk' | head -n 1)
239+
SSL_VER=\$(echo \$SSL_APK_NAME | sed 's/openssl-dev-//;s/.apk//')
240+
echo \"Detected OpenSSL Version: \$SSL_VER\"
241+
242+
# 下载并提取 ARM64 的 OpenSSL 静态库到 SysRoot
243+
mkdir -p /tmp/ssl_setup && cd /tmp/ssl_setup
244+
wget -q \$ALPINE_REPO/openssl-libs-static-\$SSL_VER.apk
245+
wget -q \$ALPINE_REPO/openssl-dev-\$SSL_VER.apk
246+
247+
# 解压到交叉编译系统的根目录
248+
for f in *.apk; do tar -xf \$f -C /crossrootfs/arm64; done
249+
cd /workspace
250+
251+
# 设置交叉编译环境变量 (强制 CMake 和编译器使用正确路径)
252+
export CROSS_COMPILE_PREFIX=\"aarch64-alpine-linux-musl-\"
253+
export CC=\"\${CROSS_COMPILE_PREFIX}clang\"
254+
export CXX=\"\${CROSS_COMPILE_PREFIX}clang++\"
255+
256+
# 告知 .NET 本地脚本去哪里找 OpenSSL 静态库
257+
export OPENSSL_ROOT_DIR=\"/crossrootfs/arm64/usr\"
258+
export OPENSSL_USE_STATIC_LIBS=TRUE
259+
260+
# 额外保险:设置 CFLAGS 让 CMake 内部探测更准确
261+
export CFLAGS=\"--sysroot=/crossrootfs/arm64 --target=aarch64-alpine-linux-musl\"
262+
263+
# 下载并安装 .NET SDK
264+
DOTNET_SDK_VERSION='${{ env.DOTNET_SDK_VERSION }}'
265+
DOTNET_SDK_URL=\"https://builds.dotnet.microsoft.com/dotnet/Sdk/\${DOTNET_SDK_VERSION}/dotnet-sdk-\${DOTNET_SDK_VERSION}-linux-x64.tar.gz\"
266+
wget -nv \"\$DOTNET_SDK_URL\" -O dotnet-sdk.tar.gz
267+
mkdir -p /opt/dotnet
268+
tar -xzf dotnet-sdk.tar.gz -C /opt/dotnet
269+
export PATH=\"/opt/dotnet:\$PATH\"
270+
271+
# 交叉编译
272+
dotnet publish src/N_m3u8DL-RE -r linux-musl-arm64 -c Release \
273+
-p:SysRoot=/crossrootfs/arm64 \
274+
-p:CppCompilerAndLinker=clang \
275+
-p:StripSymbols=true \
276+
-o /workspace/artifact
277+
"
285278
286-
- name: Package [linux-musl-arm64]
279+
- name: Package [linux-arm64]
287280
run: |
288281
cd artifact
289-
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
282+
tar -czvf ../N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz N_m3u8DL-RE
290283
291-
- name: Upload Artifact [linux-musl-arm64]
284+
- name: Upload Artifact [linux-x64]
292285
uses: actions/upload-artifact@v4
293286
with:
294-
name: linux-musl-arm64
295-
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-musl-arm64_${{ needs.set-date.outputs.date }}.tar.gz
287+
name: linux-arm64
288+
path: N_m3u8DL-RE_${{ needs.set-date.outputs.tag }}_linux-arm64_${{ needs.set-date.outputs.date }}.tar.gz
296289
297290
build-mac-x64-arm64:
298291
runs-on: macos-latest
@@ -335,8 +328,8 @@ jobs:
335328
permissions:
336329
contents: write
337330
if: ${{ github.event.inputs.doRelease == 'true' }}
338-
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]
339-
331+
needs: [set-date,build-win-nt6_0-x86,build-win-x64-arm64,build-android-bionic-x64-arm64,build-linux-musl-x64,build-linux-musl-arm64,build-mac-x64-arm64]
332+
340333
steps:
341334
- name: Fetch artifacts
342335
uses: actions/download-artifact@v4

src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace N_m3u8DL_RE.CommandLine;
1515

1616
internal static partial class CommandInvoker
1717
{
18-
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20251029";
18+
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20251228";
1919

2020
[GeneratedRegex("((best|worst)\\d*|all)")]
2121
private static partial Regex ForStrRegex();
@@ -686,9 +686,7 @@ private static MyOption GetOptions(ParseResult result)
686686
// 以用户选择语言为准优先
687687
if (option.UILanguage != null)
688688
{
689-
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(option.UILanguage);
690-
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(option.UILanguage);
691-
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(option.UILanguage);
689+
CultureUtil.ChangeCurrentCultureName(option.UILanguage);
692690
}
693691

694692
// 混流设置

src/N_m3u8DL-RE/Directory.Build.props

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@
1414
<ObjCopyName Condition="'$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">aarch64-linux-gnu-objcopy</ObjCopyName>
1515
</PropertyGroup>
1616

17+
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64' or '$(RuntimeIdentifier)' == 'linux-x64' or '$(RuntimeIdentifier)' == 'linux-arm64'">
18+
<!-- 导入libc -->
19+
<DirectPInvoke Include="libc" />
20+
</ItemGroup>
21+
22+
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64' or '$(RuntimeIdentifier)' == 'linux-x64' or '$(RuntimeIdentifier)' == 'linux-musl-x64'">
23+
<!-- 设置为纯静态应用 -->
24+
<StaticExecutable>true</StaticExecutable>
25+
<!-- 静态链接openssl -->
26+
<StaticOpenSslLinking>true</StaticOpenSslLinking>
27+
<!-- 去除国际化支持 -->
28+
<InvariantGlobalization>true</InvariantGlobalization>
29+
</PropertyGroup>
30+
1731
<!--<ItemGroup Condition="'$(PublishAot)' == 'true' and '$(RuntimeIdentifier)' != 'win-arm64' and '$(RuntimeIdentifier)' != 'linux-arm64' and '$(RuntimeIdentifier)' != 'osx-arm64' and '$(RuntimeIdentifier)' != 'osx-x64'">
1832
<PackageReference Include="PublishAotCompressed" Version="1.0.3" />
1933
</ItemGroup>-->

src/N_m3u8DL-RE/Program.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ static async Task Main(string[] args)
3636
ServicePointManager.DefaultConnectionLimit = 1024;
3737
try { Console.CursorVisible = true; } catch { }
3838

39-
string loc = ResString.CurrentLoc;
40-
string currLoc = Thread.CurrentThread.CurrentUICulture.Name;
41-
if (currLoc is "zh-CN" or "zh-SG") loc = "zh-CN";
42-
else if (currLoc.StartsWith("zh-")) loc = "zh-TW";
39+
string loc = CultureUtil.GetCurrentCultureName();
4340

4441
// 处理用户-h等请求
4542
var index = -1;
@@ -51,16 +48,7 @@ static async Task Main(string[] args)
5148

5249
ResString.CurrentLoc = loc;
5350

54-
try
55-
{
56-
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(loc);
57-
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(loc);
58-
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(loc);
59-
}
60-
catch
61-
{
62-
// Culture not work on NT6.0, so catch the exception
63-
}
51+
CultureUtil.ChangeCurrentCultureName(loc);
6452

6553
await CommandInvoker.InvokeArgs(args, DoWorkAsync);
6654
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using N_m3u8DL_RE.Common.Resource;
2+
3+
namespace N_m3u8DL_RE.Util;
4+
5+
public static class CultureUtil
6+
{
7+
public static string GetCurrentCultureName()
8+
{
9+
string loc = ResString.CurrentLoc;
10+
string currLoc = Thread.CurrentThread.CurrentUICulture.Name;
11+
12+
if (string.IsNullOrEmpty(currLoc))
13+
currLoc = GetCurrentCultureNameFromEnvironment();
14+
15+
if (currLoc is "zh-CN" or "zh-SG")
16+
loc = "zh-CN";
17+
else if (currLoc.StartsWith("zh-"))
18+
loc = "zh-TW";
19+
20+
return loc;
21+
}
22+
23+
public static void ChangeCurrentCultureName(string newName)
24+
{
25+
try
26+
{
27+
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = new System.Globalization.CultureInfo(newName);
28+
Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(newName);
29+
Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(newName);
30+
}
31+
catch (Exception)
32+
{
33+
// Culture not work on NT6.0, so catch the exception
34+
}
35+
}
36+
37+
private static string GetCurrentCultureNameFromEnvironment()
38+
{
39+
// 尝试读取 LC_ALL, LANG
40+
string langEnv = Environment.GetEnvironmentVariable("LC_ALL")
41+
?? Environment.GetEnvironmentVariable("LANG")
42+
?? ResString.CurrentLoc;
43+
return langEnv.Split('.')[0].Replace('_', '-');
44+
}
45+
}

0 commit comments

Comments
 (0)