Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ jobs:
- name: Test
shell: bash
run: dotnet test -c Release
- name: Build libminipty_unix
if: ${{ !startsWith(matrix.rid, 'win') }}
shell: bash
run: bash scripts/build-native.sh "${{ matrix.rid }}"

- name: Publish and run samples (NativeAOT)
shell: bash
run: |
Expand All @@ -66,6 +71,15 @@ jobs:
exe="$out/${sample}.exe"
fi
test -f "$exe"
if [[ "${{ matrix.rid }}" == linux-* ]]; then
test ! -f "$out/libminipty_unix.so"
test ! -f "$out/libminipty_unix.a"
fi
if [[ "${{ matrix.rid }}" == osx-* ]]; then
test ! -f "$out/libminipty_unix.dylib"
test ! -f "$out/libminipty_unix.a"
test -f "$out/minipty_spawn_helper"
fi
"$exe"
done

Expand Down Expand Up @@ -145,11 +159,17 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
rid: linux-x64
- os: ubuntu-24.04-arm
rid: linux-arm64
- os: windows-2025
rid: win-x64
- os: windows-11-arm
rid: win-arm64
- os: macos-26
rid: osx-arm64
- os: macos-26-intel
rid: osx-x64
permissions:
contents: read
runs-on: ${{ matrix.os }}
Expand All @@ -172,7 +192,7 @@ jobs:
path: ./publish
- name: Run NuGet smoke sample
shell: bash
run: bash scripts/run-nuget-smoke.sh "${MINIPTY_CI_PACKAGE_VERSION}" ./publish
run: bash scripts/run-nuget-smoke.sh "${MINIPTY_CI_PACKAGE_VERSION}" ./publish "${{ matrix.rid }}"

build-complete:
needs: [build, nuget-smoke]
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,17 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
rid: linux-x64
- os: ubuntu-24.04-arm
rid: linux-arm64
- os: windows-2025
rid: win-x64
- os: windows-11-arm
rid: win-arm64
- os: macos-26
rid: osx-arm64
- os: macos-26-intel
rid: osx-x64
permissions:
contents: read
runs-on: ${{ matrix.os }}
Expand All @@ -176,7 +182,7 @@ jobs:
path: ./publish
- name: Run NuGet smoke sample
shell: bash
run: bash scripts/run-nuget-smoke.sh "${{ needs.verify.outputs.version }}" ./publish
run: bash scripts/run-nuget-smoke.sh "${{ needs.verify.outputs.version }}" ./publish "${{ matrix.rid }}"

attest:
name: Attest packages
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<IsAotCompatible>true</IsAotCompatible>
<PackageReadmeFile>README.md</PackageReadmeFile>
<IsPackable>false</IsPackable>
<Version>1.1.0</Version>
<Version>1.2.0</Version>
<Authors>guitarrapc</Authors>
<Copyright>© guitarrapc</Copyright>
<PackageTags>pty</PackageTags>
Expand Down
4 changes: 4 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Project>
<Import Project="$(MSBuildThisFileDirectory)buildTransitive\MiniPty.targets"
Condition="Exists('$(MSBuildThisFileDirectory)buildTransitive\MiniPty.targets')" />
</Project>
56 changes: 56 additions & 0 deletions buildTransitive/MiniPty.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<Project>
<PropertyGroup>
<_MiniPtyStaticUnixRid>false</_MiniPtyStaticUnixRid>
<_MiniPtyStaticUnixRid Condition="'$(RuntimeIdentifier)' == 'linux-x64' or '$(RuntimeIdentifier)' == 'linux-arm64' or '$(RuntimeIdentifier)' == 'osx-x64' or '$(RuntimeIdentifier)' == 'osx-arm64'">true</_MiniPtyStaticUnixRid>
</PropertyGroup>

<PropertyGroup Condition="'$(PublishAot)' == 'true' and '$(_MiniPtyStaticUnixRid)' == 'true'">
<MiniPtyStaticUnixNative>true</MiniPtyStaticUnixNative>
<MiniPtyBuildUnixNative>false</MiniPtyBuildUnixNative>
</PropertyGroup>

<ItemGroup Condition="'$(MiniPtyStaticUnixNative)' == 'true'">
<DirectPInvoke Include="minipty_unix" />
<NativeLibrary Include="$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\libminipty_unix.a" />
<LinkerArg Include="-lutil" />
</ItemGroup>

<ItemGroup Condition="'$(MiniPtyStaticUnixNative)' == 'true' and $(RuntimeIdentifier.StartsWith('osx'))">
<None Include="$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\minipty_spawn_helper"
Link="minipty_spawn_helper"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest"
Condition="Exists('$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\minipty_spawn_helper')" />
</ItemGroup>

<Target Name="_MiniPtyValidateStaticArchive"
BeforeTargets="PrepareForBuild"
Condition="'$(MiniPtyStaticUnixNative)' == 'true' and !Exists('$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\libminipty_unix.a')">
<Error Text="MiniPty: missing runtimes/$(RuntimeIdentifier)/native/libminipty_unix.a. Ensure the package contains the static archive; when building from source, run: bash scripts/build-native.sh $(RuntimeIdentifier)" />
</Target>
Comment thread
guitarrapc marked this conversation as resolved.

<Target Name="_MiniPtyValidateSpawnHelper"
BeforeTargets="PrepareForBuild"
Condition="'$(MiniPtyStaticUnixNative)' == 'true' and $(RuntimeIdentifier.StartsWith('osx')) and !Exists('$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\minipty_spawn_helper')">
<Error Text="MiniPty: missing runtimes/$(RuntimeIdentifier)/native/minipty_spawn_helper (required on macOS). When building from source, run: bash scripts/build-native.sh $(RuntimeIdentifier)" />
</Target>

Comment thread
guitarrapc marked this conversation as resolved.
<!-- Drop shared shim and the link-time archive from publish output. -->
Comment thread
guitarrapc marked this conversation as resolved.
<Target Name="_MiniPtyExcludeUnixSharedNativeFromPublish"
AfterTargets="ComputeResolvedFilesToPublishList"
BeforeTargets="CopyFilesToPublishDirectory"
Condition="'$(MiniPtyStaticUnixNative)' == 'true'">
<ItemGroup>
<None Remove="@(None)"
Condition="$([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.so')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.dylib')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.a'))" />
<Content Remove="@(Content)"
Condition="$([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.so')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.dylib')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.a'))" />
<ContentWithTargetPath Remove="@(ContentWithTargetPath)"
Condition="$([System.String]::Copy('%(TargetPath)').EndsWith('libminipty_unix.so')) or $([System.String]::Copy('%(TargetPath)').EndsWith('libminipty_unix.dylib')) or $([System.String]::Copy('%(TargetPath)').EndsWith('libminipty_unix.a'))" />
<_ResolvedCopyLocalPublishAssets Remove="@(_ResolvedCopyLocalPublishAssets)"
Condition="$([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.so')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.dylib')) or $([System.String]::Copy('%(Filename)%(Extension)').Equals('libminipty_unix.a'))" />
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)"
Condition="$([System.String]::Copy('%(RelativePath)').EndsWith('libminipty_unix.so')) or $([System.String]::Copy('%(RelativePath)').EndsWith('libminipty_unix.dylib')) or $([System.String]::Copy('%(RelativePath)').EndsWith('libminipty_unix.a'))" />
</ItemGroup>
</Target>
</Project>
23 changes: 23 additions & 0 deletions scripts/build-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,35 @@ out_dir="$root/runtimes/$rid/native"

mkdir -p "$out_dir"

build_static_archive() {
local out="$1"
shift
local src
local work
local objs=()

work="$(mktemp -d)"
trap 'rm -rf "$work"; trap - RETURN' RETURN
for src in "$@"; do
local base
base="$(basename "$src")"
cp "$src" "$work/$base"
local obj="$work/${base%.c}.o"
cc -c -fPIC -O2 -I"$native_dir" -o "$obj" "$work/$base"
objs+=("$obj")
done

ar rcs "$out" "${objs[@]}"
}

case "$rid" in
linux-*)
cc -shared -fPIC -O2 -lutil -o "$out_dir/libminipty_unix.so" "${sources[@]}"
build_static_archive "$out_dir/libminipty_unix.a" "${sources[@]}"
;;
osx-*)
cc -shared -fPIC -O2 -lutil -o "$out_dir/libminipty_unix.dylib" "${sources[@]}"
build_static_archive "$out_dir/libminipty_unix.a" "${sources[@]}"
cc -O2 -o "$out_dir/minipty_spawn_helper" "$native_dir/minipty_spawn_helper.c" "$native_dir/minipty_unix_exec.c"
;;
win-*)
Expand Down
4 changes: 4 additions & 0 deletions scripts/pack-with-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ root="$(cd "$(dirname "$0")/.." && pwd)"

required=(
"linux-x64/native/libminipty_unix.so"
"linux-x64/native/libminipty_unix.a"
"linux-arm64/native/libminipty_unix.so"
"linux-arm64/native/libminipty_unix.a"
"osx-x64/native/libminipty_unix.dylib"
"osx-x64/native/libminipty_unix.a"
"osx-x64/native/minipty_spawn_helper"
"osx-arm64/native/libminipty_unix.dylib"
"osx-arm64/native/libminipty_unix.a"
"osx-arm64/native/minipty_spawn_helper"
)

Expand Down
27 changes: 25 additions & 2 deletions scripts/run-nuget-smoke.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail

version="${1:?Usage: run-nuget-smoke.sh <package-version> <nupkg-directory>}"
feed_dir="${2:?Usage: run-nuget-smoke.sh <package-version> <nupkg-directory>}"
version="${1:?Usage: run-nuget-smoke.sh <package-version> <nupkg-directory> [runtime-identifier]}"
feed_dir="${2:?Usage: run-nuget-smoke.sh <package-version> <nupkg-directory> [runtime-identifier]}"
rid="${3:-}"
version="${version#v}"

to_dotnet_path() {
Expand Down Expand Up @@ -63,3 +64,25 @@ cat > "$tmp/NuGetSmoke.csproj" <<EOF
EOF

dotnet run --project "$tmp/NuGetSmoke.csproj" -c Release --configfile "$tmp/nuget.config"

if [[ -n "$rid" ]]; then
out="$tmp/aot-publish"
dotnet publish "$tmp/NuGetSmoke.csproj" -c Release -r "$rid" \
--self-contained true -p:PublishAot=true -p:StripSymbols=true -p:DebugType=None \
-o "$out" --configfile "$tmp/nuget.config"
exe="$out/NuGetSmoke"
if [[ "$rid" == win-* ]]; then
exe="$out/NuGetSmoke.exe"
fi
test -f "$exe"
if [[ "$rid" == linux-* ]]; then
test ! -f "$out/libminipty_unix.so"
test ! -f "$out/libminipty_unix.a"
fi
if [[ "$rid" == osx-* ]]; then
test ! -f "$out/libminipty_unix.dylib"
test ! -f "$out/libminipty_unix.a"
test -f "$out/minipty_spawn_helper"
fi
"$exe"
fi
10 changes: 9 additions & 1 deletion src/MiniPty/MiniPty.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<MiniPtyPackUnixNative Condition="'$(MiniPtyPackUnixNative)' == ''">false</MiniPtyPackUnixNative>
<_MiniPtyRuntimesRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\runtimes'))</_MiniPtyRuntimesRoot>
<MiniPtyBuildUnixNative Condition="'$(MiniPtyPackUnixNative)' == 'true'">false</MiniPtyBuildUnixNative>
<MiniPtyBuildUnixNative Condition="'$(MiniPtyStaticUnixNative)' == 'true'">false</MiniPtyBuildUnixNative>
<MiniPtyBuildUnixNative Condition="'$(MiniPtyBuildUnixNative)' == '' and ($([MSBuild]::IsOSPlatform('Linux')) Or $([MSBuild]::IsOSPlatform('OSX')) Or $([MSBuild]::IsOSPlatform('FreeBSD')))">true</MiniPtyBuildUnixNative>
<MiniPtyUnixNativeLibraryName Condition="$([MSBuild]::IsOSPlatform('OSX'))">libminipty_unix.dylib</MiniPtyUnixNativeLibraryName>
<MiniPtyUnixNativeLibraryName Condition="'$(MiniPtyUnixNativeLibraryName)' == ''">libminipty_unix.so</MiniPtyUnixNativeLibraryName>
Expand All @@ -33,6 +34,7 @@

<ItemGroup Condition="'$(MiniPtyPackUnixNative)' == 'true'">
<None Include="$(_MiniPtyRuntimesRoot)\**\*.so;
$(_MiniPtyRuntimesRoot)\**\*.a;
$(_MiniPtyRuntimesRoot)\**\*.dylib"
Pack="true"
PackagePath="runtimes/%(RecursiveDir)%(Filename)%(Extension)" />
Expand All @@ -45,6 +47,12 @@
PackagePath="runtimes/osx-x64/native" />
</ItemGroup>

<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)..\..\buildTransitive\MiniPty.targets"
Pack="true"
PackagePath="buildTransitive/" />
</ItemGroup>
Comment thread
guitarrapc marked this conversation as resolved.

<Target Name="BuildMiniPtyUnixNative" BeforeTargets="AssignTargetPaths"
Condition="'$(MiniPtyBuildUnixNative)' == 'true'">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
Expand All @@ -56,7 +64,7 @@
<None Include="$(_MiniPtyUnixNativeOutput)">
<Link>$(MiniPtyUnixNativeLibraryName)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToPublishDirectory Condition="'$(MiniPtyStaticUnixNative)' != 'true'">PreserveNewest</CopyToPublishDirectory>
</None>
<FileWrites Include="$(_MiniPtySpawnHelperOutput)" Condition="$([MSBuild]::IsOSPlatform('OSX'))" />
<None Include="$(_MiniPtySpawnHelperOutput)" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
Expand Down
5 changes: 3 additions & 2 deletions tests/MiniPty.Tests/PtyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1041,10 +1041,11 @@ public async Task PtyChildSeesResizedSize()
if (!TryResolveWindowsPowerShell(out var powershell))
return;

// Block on stdin until after Resize so a fast runner cannot query size before ConPTY applies it.
await using var session = Pty.Start(
Spawn(powershell, ["-NoLogo", "-NoProfile", "-Command", "$s = $Host.UI.RawUI.WindowSize; Start-Sleep -Milliseconds 200; Write-Output (\"{0} {1}\" -f $s.Width, $s.Height); exit 0"]));
Spawn(powershell, ["-NoLogo", "-NoProfile", "-Command", "[Console]::In.ReadLine() | Out-Null; $s = $Host.UI.RawUI.WindowSize; Write-Output (\"{0} {1}\" -f $s.Width, $s.Height); exit 0"]));
session.Resize(new(100, 30));
var result = await session.CompleteAsync();
var result = await session.CompleteAsync(new PtyCompleteOptions { Input = "go\r\n" });

await Assert.That(result.ExitCode).IsEqualTo(0);
await Assert.That(result.Contains("100 30")).IsTrue();
Expand Down