Skip to content

Commit c42b7c7

Browse files
committed
fix nupkg deps not found error
1 parent c51820d commit c42b7c7

6 files changed

Lines changed: 241 additions & 3 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
*/obj/
44
pty-terminal.debug
55
*/Properties/
6-
*.user
6+
*.user
7+
NupkgVerify/NupkgVerify.csproj
8+
NupkgVerify/Program.cs

Pty.Net/Pty.Net.csproj

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1616
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
1717
<PackageLicenseExpression>MIT</PackageLicenseExpression>
18-
<Version>1.0.1</Version>
18+
<Version>1.0.2</Version>
1919
</PropertyGroup>
2020

2121
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -30,13 +30,22 @@
3030
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
3131
</Content>
3232
-->
33-
<Content Include="deps\**" Exclude="deps\**\*.pdb">
33+
<Content Include="deps\**\*.*" Exclude="deps\**\*.pdb;deps\**\*.lib;deps\**\*.exp">
3434
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3535
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
3636
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
3737
</Content>
3838
</ItemGroup>
3939

40+
<ItemGroup>
41+
<!--
42+
NuGet 引用方默认不会把 content/contentFiles 复制到输出目录。
43+
通过 buildTransitive 注入 targets,把包内 content/deps 复制到引用方 bin/publish 的 deps 目录。
44+
-->
45+
<None Include="buildTransitive\PTY.targets" Pack="true" PackagePath="buildTransitive\PTY.targets" />
46+
<None Include="build\PTY.targets" Pack="true" PackagePath="build\PTY.targets" />
47+
</ItemGroup>
48+
4049
<!-- NuGet.org 符号包校验:snupkg 里的每个 PDB 都必须能在 nupkg 的 lib/ref 中找到同名 DLL。
4150
deps 下的 native PDB(如 conptylib.pdb,仅有 .lib 无 .dll)会导致 symbols 发布失败。
4251
即使项目已 Exclude 掉 pdb,旧的输出目录残留也可能被打进 snupkg,因此在 Pack 前强制清理。 -->

Pty.Net/build/PTY.targets

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project>
2+
<!--
3+
PTY NuGet 运行时依赖拷贝规则(直接引用时使用 build/,间接引用时使用 buildTransitive/)
4+
5+
说明同 buildTransitive/PTY.targets。
6+
-->
7+
8+
<PropertyGroup>
9+
<_PtyPackageRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\'))</_PtyPackageRoot>
10+
<_PtyDepsSourceDir>$(_PtyPackageRoot)content\deps\</_PtyDepsSourceDir>
11+
</PropertyGroup>
12+
13+
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
14+
<_PtyDepsFiles Include="$(_PtyDepsSourceDir)**\*.*" />
15+
</ItemGroup>
16+
17+
<Target Name="_PtyCopyDepsToOutput" AfterTargets="Build" Condition="'$(OS)' == 'Windows_NT' and Exists('$(_PtyDepsSourceDir)')">
18+
<Copy
19+
SourceFiles="@(_PtyDepsFiles)"
20+
DestinationFiles="@(_PtyDepsFiles->'$(TargetDir)deps\%(RecursiveDir)%(Filename)%(Extension)')"
21+
SkipUnchangedFiles="true" />
22+
</Target>
23+
24+
<Target Name="_PtyCopyDepsToPublish" AfterTargets="Publish" Condition="'$(OS)' == 'Windows_NT' and Exists('$(_PtyDepsSourceDir)') and '$(PublishDir)' != ''">
25+
<Copy
26+
SourceFiles="@(_PtyDepsFiles)"
27+
DestinationFiles="@(_PtyDepsFiles->'$(PublishDir)deps\%(RecursiveDir)%(Filename)%(Extension)')"
28+
SkipUnchangedFiles="true" />
29+
</Target>
30+
</Project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Project>
2+
<!--
3+
PTY NuGet 运行时依赖拷贝规则
4+
5+
背景:库代码用 [DllImport("deps\\...")] 这种相对路径加载 native DLL。
6+
NuGet 的 content/contentFiles 默认不会自动复制到引用项目的输出目录,导致运行时找不到 deps\...\*.dll。
7+
8+
方案:通过 buildTransitive targets,在引用项目 Build/Publish 后把包内 content/deps/** 复制到输出目录的 deps/**。
9+
-->
10+
11+
<PropertyGroup>
12+
<_PtyPackageRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\'))</_PtyPackageRoot>
13+
<_PtyDepsSourceDir>$(_PtyPackageRoot)content\deps\</_PtyDepsSourceDir>
14+
</PropertyGroup>
15+
16+
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
17+
<_PtyDepsFiles Include="$(_PtyDepsSourceDir)**\*.*" />
18+
</ItemGroup>
19+
20+
<Target Name="_PtyCopyDepsToOutput" AfterTargets="Build" Condition="'$(OS)' == 'Windows_NT' and Exists('$(_PtyDepsSourceDir)')">
21+
<Copy
22+
SourceFiles="@(_PtyDepsFiles)"
23+
DestinationFiles="@(_PtyDepsFiles->'$(TargetDir)deps\%(RecursiveDir)%(Filename)%(Extension)')"
24+
SkipUnchangedFiles="true" />
25+
</Target>
26+
27+
<Target Name="_PtyCopyDepsToPublish" AfterTargets="Publish" Condition="'$(OS)' == 'Windows_NT' and Exists('$(_PtyDepsSourceDir)') and '$(PublishDir)' != ''">
28+
<Copy
29+
SourceFiles="@(_PtyDepsFiles)"
30+
DestinationFiles="@(_PtyDepsFiles->'$(PublishDir)deps\%(RecursiveDir)%(Filename)%(Extension)')"
31+
SkipUnchangedFiles="true" />
32+
</Target>
33+
</Project>

nuget-verify.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0nuget-verify.ps1" -Mode Full

nuget-verify.ps1

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
param(
2+
[ValidateSet('Simple', 'Full')]
3+
[string]$Mode = 'Full',
4+
# 默认取 Pty.Net.csproj 里的 <Version>;也可手动传入(例如 1.0.2-local)
5+
[string]$Version
6+
)
7+
8+
$ErrorActionPreference = 'Stop';
9+
10+
$root = (Resolve-Path -LiteralPath $PSScriptRoot).Path;
11+
$projDir = Join-Path $root 'NupkgVerify';
12+
$releaseDir = Join-Path $root 'Pty.Net\bin\Release';
13+
$csproj = Join-Path $root 'Pty.Net\Pty.Net.csproj';
14+
15+
function Get-Version {
16+
[xml]$xml = Get-Content $csproj;
17+
$pg = @($xml.Project.PropertyGroup) | Where-Object { $_ -and $_.Version } | Select-Object -First 1;
18+
if (-not $pg -or -not $pg.Version) {
19+
throw "<Version> not found in: $csproj";
20+
}
21+
return [string]$pg.Version;
22+
}
23+
24+
function New-PtyNupkgVerifyProject {
25+
if (-not (Test-Path $projDir)) {
26+
dotnet new console -n NupkgVerify -o $projDir -f net8.0;
27+
}
28+
}
29+
30+
function Get-LatestNupkgPath([string]$ver = $null) {
31+
if (-not (Test-Path $releaseDir)) { throw "Release dir not found: $releaseDir" }
32+
33+
$pattern = if ($ver) { "PTY.$ver*.nupkg" } else { 'PTY.*.nupkg' };
34+
$pkg = Get-ChildItem $releaseDir -Filter $pattern |
35+
Where-Object { $_.Name -notmatch '\.snupkg$' } |
36+
Sort-Object LastWriteTime -Descending |
37+
Select-Object -First 1;
38+
39+
if (-not $pkg) {
40+
throw "nupkg not found in $releaseDir (pattern: $pattern)";
41+
}
42+
return $pkg.FullName;
43+
}
44+
45+
function Test-ZipHasEntry([System.IO.Compression.ZipArchive]$zip, [string]$fullName) {
46+
return [bool]($zip.Entries | Where-Object { $_.FullName -eq $fullName } | Select-Object -First 1)
47+
}
48+
49+
function Test-ZipHasAnyEntryLike([System.IO.Compression.ZipArchive]$zip, [string]$regex) {
50+
return [bool]($zip.Entries | Where-Object { $_.FullName -match $regex } | Select-Object -First 1)
51+
}
52+
53+
function Test-PtyNupkgLayout([string]$pkgPath) {
54+
if (-not (Test-Path $pkgPath)) { throw "nupkg not found: $pkgPath" }
55+
56+
Add-Type -AssemblyName System.IO.Compression.FileSystem;
57+
$zip = [System.IO.Compression.ZipFile]::OpenRead($pkgPath);
58+
try {
59+
"--- verifying nupkg ---";
60+
"pkg: $pkgPath";
61+
62+
# 1) 必须包含 build / buildTransitive targets
63+
if (-not (Test-ZipHasEntry $zip 'build/PTY.targets')) { throw 'MISSING in nupkg: build/PTY.targets' }
64+
if (-not (Test-ZipHasEntry $zip 'buildTransitive/PTY.targets')) { throw 'MISSING in nupkg: buildTransitive/PTY.targets' }
65+
66+
# 2) 必须包含 content/deps(targets 会从 content/deps 复制到输出 deps)
67+
if (-not (Test-ZipHasAnyEntryLike $zip '^content/deps/')) { throw 'MISSING in nupkg: content/deps/**' }
68+
69+
# 3) Windows 关键文件(按仓库 deps 结构)
70+
if (-not (Test-ZipHasEntry $zip 'content/deps/conpty/os64/conpty.dll')) { throw 'MISSING in nupkg: content/deps/conpty/os64/conpty.dll' }
71+
if (-not (Test-ZipHasEntry $zip 'content/deps/conpty/os86/conpty.dll')) { throw 'MISSING in nupkg: content/deps/conpty/os86/conpty.dll' }
72+
if (-not (Test-ZipHasEntry $zip 'content/deps/winpty/winpty.dll')) { throw 'MISSING in nupkg: content/deps/winpty/winpty.dll' }
73+
if (-not (Test-ZipHasEntry $zip 'content/deps/winpty/winpty.exe')) { throw 'MISSING in nupkg: content/deps/winpty/winpty.exe' }
74+
if (-not (Test-ZipHasEntry $zip 'content/deps/winpty/winpty-agent.exe')) { throw 'MISSING in nupkg: content/deps/winpty/winpty-agent.exe' }
75+
if (-not (Test-ZipHasEntry $zip 'content/deps/winpty/winpty-debugserver.exe')) { throw 'MISSING in nupkg: content/deps/winpty/winpty-debugserver.exe' }
76+
77+
# 4) 不应该把 native 的 pdb/lib/exp 打进 nupkg(csproj 已 Exclude,这里再验一遍)
78+
$bad = $zip.Entries | Where-Object { $_.FullName -match '^content/deps/.+\.(pdb|lib|exp)$' } | Select-Object -ExpandProperty FullName;
79+
if ($bad) {
80+
"--- unexpected native artifacts in nupkg ---";
81+
$bad;
82+
throw "nupkg contains excluded native artifacts under content/deps (pdb/lib/exp)";
83+
}
84+
85+
"OK: nupkg layout verified";
86+
}
87+
finally {
88+
$zip.Dispose();
89+
}
90+
}
91+
92+
function Test-PtyNupkgSimple {
93+
$ver = if ($Version) { $Version } else { Get-Version };
94+
if (Test-Path $projDir) { Remove-Item $projDir -Recurse -Force };
95+
New-PtyNupkgVerifyProject;
96+
Push-Location $projDir;
97+
dotnet add package PTY -v $ver -s $releaseDir;
98+
dotnet build;
99+
Pop-Location;
100+
$out = Join-Path $projDir "bin\Debug\net8.0\deps\conpty\os64\conpty.dll";
101+
if (Test-Path $out) { "OK: copied -> $out" } else { "MISSING: $out" }
102+
}
103+
104+
function Test-PtyNupkgFull {
105+
$ver = if ($Version) { $Version } else { Get-Version };
106+
107+
# 1) 重新打包(输出在 Pty.Net\bin\Release)
108+
dotnet pack $csproj -c Release;
109+
110+
# 2) 找到刚生成的 nupkg,并做结构校验(build/buildTransitive + content/deps)
111+
$pkg = Get-LatestNupkgPath $ver;
112+
Test-PtyNupkgLayout $pkg;
113+
114+
# 3) 清理 NupkgVerify 对 PTY 的缓存安装(只删这个版本,别全局清)
115+
$ptyCacheRoot = Join-Path $env:USERPROFILE '.nuget\packages\pty';
116+
$ptyCacheVer = Join-Path $ptyCacheRoot $ver;
117+
if (Test-Path $ptyCacheVer) { Remove-Item $ptyCacheVer -Recurse -Force };
118+
119+
# 4) 让 NupkgVerify 从本地包源安装这个版本并重新编译
120+
New-PtyNupkgVerifyProject;
121+
Push-Location $projDir;
122+
dotnet add package PTY -v $ver -s $releaseDir;
123+
dotnet restore;
124+
dotnet build;
125+
Pop-Location;
126+
127+
# 5) 验证输出目录是否出现 deps,并检查关键文件
128+
$p = Join-Path $projDir "bin\Debug\net8.0\deps";
129+
if (Test-Path $p) {
130+
"deps exists";
131+
$expected = @(
132+
(Join-Path $p 'conpty\os64\conpty.dll'),
133+
(Join-Path $p 'conpty\os86\conpty.dll'),
134+
(Join-Path $p 'winpty\winpty.dll'),
135+
(Join-Path $p 'winpty\winpty.exe'),
136+
(Join-Path $p 'winpty\winpty-agent.exe'),
137+
(Join-Path $p 'winpty\winpty-debugserver.exe')
138+
);
139+
$missing = $expected | Where-Object { -not (Test-Path $_) };
140+
if ($missing) {
141+
"--- missing deps outputs ---";
142+
$missing;
143+
throw 'deps copied but some expected files are missing';
144+
}
145+
"OK: deps files exist in output";
146+
}
147+
else {
148+
"deps missing";
149+
}
150+
}
151+
152+
if ($Mode -eq 'Simple') {
153+
Test-PtyNupkgSimple;
154+
}
155+
else {
156+
Test-PtyNupkgFull;
157+
}
158+
159+
# 兼容:保留旧命名习惯(如你有 dot-source 后手动调用)
160+
# Set-Alias -Name Verify-Nupkg -Value Test-PtyNupkgLayout -Scope Script -Force;
161+
# Set-Alias -Name Ensure-VerifyProject -Value New-PtyNupkgVerifyProject -Scope Script -Force;
162+
# Set-Alias -Name Nupkg-Verify-Simple -Value Test-PtyNupkgSimple -Scope Script -Force;
163+
# Set-Alias -Name Nupkg-Verify-Full -Value Test-PtyNupkgFull -Scope Script -Force;

0 commit comments

Comments
 (0)