Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
da52245
Claude: Add the native Windows WIN64 platform and win64-debug, win64-…
winlinvip Oct 3, 2026
3a8bee6
Claude: Make public.h portable to native Windows (MSVC) with POSIX na…
winlinvip Oct 3, 2026
7871288
Claude: Add the native Windows WIN64 platform branch to md.h and comm…
winlinvip Oct 3, 2026
9ce3fd9
Claude: Add native Windows WIN64 stubs so the ST library links with M…
winlinvip Oct 3, 2026
d567486
Claude: Build the utest with MSVC through utest/Makefile for native W…
winlinvip Oct 3, 2026
d6b2d67
Claude: Add a native Windows build-only CI job with MSVC and GNU make.
winlinvip Oct 3, 2026
58a7bda
Claude: Build the utest with CMake and MSVC for a Visual Studio proje…
winlinvip Oct 3, 2026
50e04d5
Claude: Port the context switch to native Windows x64 with MASM in md…
winlinvip Oct 3, 2026
6220346
Claude: Set the TIB stack bounds of new threads on native Windows x64.
winlinvip Oct 3, 2026
ae77fd6
Claude: Allocate coroutine stacks with VirtualAlloc and red zones on …
winlinvip Oct 3, 2026
db03ec0
Claude: Add a minimal native Windows event dispatch that waits for th…
winlinvip Oct 3, 2026
fc2bb04
Claude: Start new threads in an assembly entry on native Windows x64,…
winlinvip Oct 3, 2026
9aeec72
Claude: Add utests for live registers across switches and deep recurs…
winlinvip Oct 3, 2026
f3cd2a9
Claude: Run st_utest in the native Windows CI job, without the socket…
winlinvip Oct 3, 2026
bf43bea
Claude: Map Winsock errors to errno on native Windows.
winlinvip Oct 3, 2026
5ebcc4b
Claude: Start Winsock in st_init and clean it up in st_destroy on nat…
winlinvip Oct 3, 2026
2c6b91f
Claude: Implement the socket I/O calls with Winsock on native Windows.
winlinvip Oct 3, 2026
36ab01b
Claude: Make the utest stream pair a loopback TCP connection on nativ…
winlinvip Oct 3, 2026
d6dd107
Claude: Add the WSAPoll event system on native Windows.
winlinvip Oct 3, 2026
5449429
Claude: Fix or skip the Windows IoWriteTest and refused-connect tests.
winlinvip Oct 3, 2026
7b144e5
Claude: Add an echo utest with 1000 concurrent TCP connections.
winlinvip Oct 3, 2026
4f7e35a
Claude: Check MSVC AddressSanitizer with MD_ASAN on native Windows.
winlinvip Oct 3, 2026
0507ba7
Claude: Port the porting, helloworld, and verify tools to MSVC.
winlinvip Oct 3, 2026
aa1c270
Claude: Document native Windows x64 with MSVC. v1.9.2
winlinvip Oct 3, 2026
5c54e1c
Claude: Run the integration tools on native Windows with auto/tools.sh.
winlinvip Oct 3, 2026
4572045
Claude: Run the time, key, and lifecycle tools on native Windows.
winlinvip Oct 3, 2026
63c1052
Claude: Run the tcp tool on native Windows.
winlinvip Oct 3, 2026
0b7f954
Claude: Skip the lifecycle fd-limit check on native Windows.
winlinvip Oct 3, 2026
3e09641
Claude: Run the udp tool on native Windows.
winlinvip Oct 3, 2026
e7405d8
Claude: Run the poll tool on native Windows.
winlinvip Oct 3, 2026
ae9a9c3
Claude: Run the stress tool on native Windows.
winlinvip Oct 3, 2026
cfb07ab
Claude: Run the backtrace tool on native Windows.
winlinvip Oct 3, 2026
892d681
Claude: Skip the pipe tool on native Windows.
winlinvip Oct 3, 2026
e0f8dca
Claude: Run the unix tool on native Windows.
winlinvip Oct 3, 2026
156d325
Claude: Run the integration tools in the Windows CI job, and document…
winlinvip Oct 3, 2026
580eb63
Claude: Add the C++ exception tool for C++ exceptions and SEH on coro…
winlinvip Oct 4, 2026
1993302
Claude: Fix the UtestPairTest hang on macOS by sending the 64 KB in p…
winlinvip Oct 4, 2026
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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Shell scripts keep LF on every checkout, so bash in WSL can run a Windows checkout.
*.sh text eol=lf
68 changes: 66 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,81 @@ jobs:
files: coverage.xml
disable_search: true

# Native Windows with MSVC, built with GNU make from Git Bash. Runs st_utest, then
# auto/tools.sh in the ST default and SRS builds, as on Linux and macOS.
windows:
name: actions-test-build-win64
runs-on: windows-latest

steps:
- name: Checkout repository
uses: actions/checkout@v7

################################################################
# Build
- name: Setup MSVC environment
shell: pwsh
run: |
# Pass the vcvars64.bat environment to the next steps: INCLUDE, LIB, LIBPATH,
# and only the PATH directories that vcvars64.bat adds.
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vs = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if (-not $vs) { throw "No Visual Studio with the MSVC x64 tools" }
$vars = cmd /c "`"$vs\VC\Auxiliary\Build\vcvars64.bat`" >nul && set"
if ($LASTEXITCODE -ne 0) { throw "vcvars64.bat failed" }
$old = $env:PATH -split ';'
foreach ($line in $vars) {
if ($line -match '^(INCLUDE|LIB|LIBPATH)=(.*)$') {
[IO.File]::AppendAllText($env:GITHUB_ENV, "$($Matches[1])=$($Matches[2])`n")
} elseif ($line -match '^PATH=(.*)$') {
foreach ($dir in $Matches[1] -split ';') {
if ($dir -and $old -notcontains $dir) { [IO.File]::AppendAllText($env:GITHUB_PATH, "$dir`n") }
}
}
}
- name: Build ST and utest with MSVC
shell: bash
run: |
command -v make >/dev/null || choco install make --no-progress -y
command -v make cl ml64 lib
make win64-debug-utest
test -f obj/st_utest.exe

################################################################
# Tests
- name: Run ST utest
shell: bash
timeout-minutes: 10
run: ./obj/st_utest.exe
- name: Run ST tools
shell: bash
timeout-minutes: 10
run: ./auto/tools.sh
- name: Run ST tools in the SRS build
shell: bash
timeout-minutes: 10
run: EXTRA_CFLAGS=-DMALLOC_STACK ./auto/tools.sh

################################################################
# Build
- name: Build optimized ST with MSVC
shell: bash
run: |
make win64-optimized
test -f obj/libst.a

# The single check to require for merging. It runs even when a needed job
# fails, because a skipped required check counts as passed.
final:
name: actions-test-final
runs-on: ubuntu-24.04
needs: [utest, coverage]
needs: [utest, coverage, windows]
if: always()

steps:
- name: Check all jobs succeeded
run: |
echo "utest: ${{ needs.utest.result }}, coverage: ${{ needs.coverage.result }}"
echo "utest: ${{ needs.utest.result }}, coverage: ${{ needs.coverage.result }}, windows: ${{ needs.windows.result }}"
test "${{ needs.utest.result }}" = success
test "${{ needs.coverage.result }}" = success
test "${{ needs.windows.result }}" = success
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
DARWIN_*_DBG
LINUX_*_DBG
CYGWIN64_*_DBG
WIN64_*_DBG
WIN64_*_OPT
tools/*/*.exe
tools/*/*.obj
tools/*/*.ilk
tools/*/*.pdb
obj
st.pc
.idea
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ The changelog for the [srs](https://github.com/ossrs/state-threads/tree/srs) bra

## ST 1.9 Changelog

* 2026-10-03, Windows: Support native Windows x64 with MSVC, MASM, and WSAPoll, built by GNU make. v1.9.2
* 2026-10-03, Tools: Add integration tools for every public API, run by auto/tools.sh in CI, [#41](https://github.com/ossrs/state-threads/pull/41). v1.9.1
* 2026-09-30, Changelog: Move the change list from README to CHANGELOG.md, and add the patch version. v1.9.0

Expand Down
59 changes: 52 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@
# GPL.

# This is the full version of the libst library - modify carefully
VERSION = 1.9.1
VERSION = 1.9.2

##########################
# Supported OSes:
#
#OS = DARWIN
#OS = LINUX
#OS = WIN64

# Please see the "Other possible defines" section below for
# possible compilation options.
Expand Down Expand Up @@ -77,6 +78,13 @@ ARFLAGS = -r
LNFLAGS = -s
DSO_SUFFIX = so

# The output flags of the compiler and archiver, the debug flags, and the
# command that points obj at TARGETDIR. WIN64 (MSVC) overrides them.
CC_OUT = -o $(EMPTY)
AR_OUT =
DBG_FLAGS = -g -O0
LINK_OBJ = $(LN) $(LNFLAGS) $(TARGETDIR) obj

MAJOR = $(shell echo $(VERSION) | sed 's/^\([^\.]*\).*/\1/')
DESC = st.pc

Expand All @@ -86,11 +94,13 @@ DESC = st.pc

TARGETS = darwin-debug darwin-optimized \
linux-debug linux-optimized \
cygwin64-debug
cygwin64-debug \
win64-debug win64-optimized

UTEST_TARGETS = darwin-debug-utest linux-debug-utest \
darwin-debug-gcov linux-debug-gcov \
cygwin64-debug-utest
cygwin64-debug-utest \
win64-debug-utest

#
# Platform specifics
Expand Down Expand Up @@ -127,6 +137,23 @@ OTHER_FLAGS = -Wall
DEFINES += -DMD_HAVE_SELECT
endif

# Native Windows x64 with MSVC (cl, lib), not CYGWIN64. Run GNU make from Git
# Bash or PowerShell with the MSVC environment on PATH. Static library only.
# Git Bash 'ln -s' copies instead of linking, so obj is a directory junction.
ifeq ($(OS), WIN64)
EXTRA_OBJS = $(TARGETDIR)/md_win64.o
CC = cl
CXX = cl
AR = lib
RANLIB = true
ARFLAGS = -nologo
CC_OUT = -Fo
AR_OUT = -OUT:
DBG_FLAGS = -Z7 -Od
LINK_OBJ = MSYS2_ARG_CONV_EXCL='*' cmd /c mklink /J obj $(TARGETDIR) >/dev/null
OTHER_FLAGS = -nologo -W4
endif

#
# End of platform section.
##########################
Expand All @@ -135,7 +162,7 @@ endif
ifeq ($(BUILD), OPT)
OTHER_FLAGS += -O2
else
OTHER_FLAGS += -g -O0
OTHER_FLAGS += $(DBG_FLAGS)
DEFINES += -DDEBUG
endif

Expand Down Expand Up @@ -199,6 +226,9 @@ endif
# or enable support for asan:
# make EXTRA_CFLAGS="-DMD_ASAN -fsanitize=address -fno-omit-frame-pointer"
#
# or enable support for asan on native Windows, where cl has no -fno-omit-frame-pointer:
# make win64-debug EXTRA_CFLAGS="-DMD_ASAN -fsanitize=address"
#
# or to disable the clock_gettime for MacOS before 10.12, see https://github.com/ossrs/srs/issues/3978
# make EXTRA_CFLAGS=-DMD_OSX_NO_CLOCK_GETTIME
#
Expand Down Expand Up @@ -261,13 +291,13 @@ st.pc: st.pc.in
# Point obj to this platform on every build, even when the library is up to date.
.PHONY: obj-link
obj-link:
rm -f obj; $(LN) $(LNFLAGS) $(TARGETDIR) obj
rm -f obj; $(LINK_OBJ)

$(TARGETDIR):
if [ ! -d $(TARGETDIR) ]; then mkdir $(TARGETDIR); fi

$(SLIBRARY): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
$(AR) $(ARFLAGS) $(AR_OUT)$@ $(OBJS)
$(RANLIB) $@

$(DLIBRARY): $(OBJS:%.o=%-pic.o)
Expand All @@ -286,8 +316,14 @@ $(HEADER): public.h
$(TARGETDIR)/%.o: %.S
$(CC) $(CFLAGS) -c $< -o $@

# The WIN64 context switch is MASM assembly, md_win64.asm.
ifeq ($(OS), WIN64)
$(TARGETDIR)/%.o: %.asm
ml64 -nologo -c -Fo$@ $<
endif

$(TARGETDIR)/%.o: %.c common.h md.h
$(CC) $(CFLAGS) -c $< -o $@
$(CC) $(CFLAGS) -c $< $(CC_OUT)$@

# Note that we use C++98 standard for the C++ files.
$(TARGETDIR)/%.o: %.cc common.h md.h
Expand Down Expand Up @@ -325,6 +361,11 @@ linux-optimized:
cygwin64-debug:
$(MAKE) OS="CYGWIN64" BUILD="DBG"

win64-debug:
$(MAKE) OS="WIN64" BUILD="DBG"
win64-optimized:
$(MAKE) OS="WIN64" BUILD="OPT"

darwin-debug-utest:
@echo "Build utest for state-threads"
$(MAKE) OS="DARWIN" BUILD="DBG"
Expand All @@ -337,6 +378,10 @@ cygwin64-debug-utest:
@echo "Build utest for state-threads"
$(MAKE) OS="CYGWIN64" BUILD="DBG"
cd utest && $(MAKE) UTEST_FLAGS="-std=gnu++0x" # @see https://www.codenong.com/18784112/
win64-debug-utest:
@echo "Build utest for state-threads"
$(MAKE) OS="WIN64" BUILD="DBG"
cd utest && $(MAKE) OS="WIN64"

darwin-debug-gcov:
@echo "Build utest with gcov for state-threads"
Expand Down
86 changes: 83 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,42 @@ Get code:
git clone -b srs https://github.com/ossrs/state-threads.git
```

For Cygwin(Windows):
Native Windows x64 builds with the Visual Studio (MSVC) toolchain, `cl`, `ml64`, and `lib`, through GNU make
and the same Makefile. There is no Cygwin, MinGW, WSL, or POSIX emulation layer: GNU make and Git Bash only
run the build, and the output is the static library `obj/libst.a` built by MSVC. It needs Windows 10 1809 or
Windows Server 2019 or later, x64.

Install the build tools:

* Visual Studio 2022, or its Build Tools, with the MSVC x64 tools (the "Desktop development with C++" workload).
* [Git for Windows](https://git-scm.com/download/win), for Git Bash.
* GNU make, for example `winget install ezwinports.make` or `choco install make`.

Open the `x64 Native Tools Command Prompt for VS 2022`, which runs `vcvars64.bat` and puts `cl`, `ml64`, and
`lib` on `PATH`, then start Git Bash in it:

```
make cygwin64-debug
"C:\Program Files\Git\bin\bash.exe"
```

> Remark: Windows native build is unsupported right now.
For Windows, build the debug or the optimized library:

```bash
make win64-debug
make win64-optimized
```

> Note: Programs that include `st.h` must include it before `windows.h`, or define `WIN32_LEAN_AND_MEAN`. The
> library links `ws2_32.lib` by itself. For what works differently on Windows, read the
> [porting notes](docs/notes.html#windows).

Windows with ASAN(Google Address Sanitizer), where cl has no `-fno-omit-frame-pointer`:

```bash
make win64-debug EXTRA_CFLAGS="-DMD_ASAN -fsanitize=address"
```

> Remark: Cygwin64 is deprecated, do not use it. Use native Windows, as above.

## Branch SRS

Expand Down Expand Up @@ -148,6 +177,57 @@ To make ST with utest and run it:
make darwin-debug-utest && ./obj/st_utest
```

## Windows: UTest

> Note: We use [Google test](https://github.com/google/googletest/releases/tag/release-1.11.0) in `utest/gtest-fit`.

To make ST with utest and run it, in Git Bash with the MSVC environment (see [Windows: Usage](#windows-usage)):

```bash
make win64-debug-utest && ./obj/st_utest.exe
```

The tests that need POSIX features (fork, signals, pipes, files) are not built on Windows, and a few are
skipped with a reason, for example the write tests that need a partial send, which Winsock never does.

To debug in Visual Studio, generate a solution with CMake, which comes with Visual Studio, from the
`x64 Native Tools Command Prompt for VS 2022`, then open `C:\st-build\st.sln`:

```
cmake -S cmake -B C:\st-build -G "Visual Studio 17 2022" -A x64
cmake --build C:\st-build --config Debug --target st_utest
```

> Note: Use a short build directory, because MSBuild fails when its paths are too long. The Makefile stays the
> main build, and CMake also builds the `helloworld`, `porting`, and `verify` tools.

## Windows: Tools

The integration tools in `tools/` build with MSVC and run with the same runner as on Linux and macOS, in Git
Bash with the MSVC environment (see [Windows: Usage](#windows-usage)). It builds the library with
`make -B win64-debug`, then builds each tool and runs `<name>.exe` with `ST_TOOL_EVENTSYS=select` and `alt`
(both are WSAPoll on Windows), and prints `All tools OK`. Run it in the ST default build and in the SRS
build, as CI does:

```bash
./auto/tools.sh
EXTRA_CFLAGS=-DMALLOC_STACK ./auto/tools.sh
```

The arguments name the tools to run, for example `./auto/tools.sh tcp udp`. The runner leaves the library
built with `EXTRA_CFLAGS`, so rebuild with `make -B win64-debug-utest` before the utest.

On Windows, ST is sockets only, so the tools make each pipe a loopback TCP pair and each `socketpair` an
`AF_UNIX` stream pair, or a loopback UDP pair for datagrams. The `pipe` tool, which needs pipes, FIFOs,
`st_open` files, and signals, prints `SKIP pipe: <why>` instead of `OK`. A few checks that Windows does not
support are skipped there, each with a comment: the partial writes on timeout in `tcp` (Winsock never sends
part of a non-blocking send), the `RLIMIT_NOFILE` checks in `lifecycle` and `stress`, reading back
`O_NONBLOCK` in `poll`, and the `AF_UNIX` datagram echo and the `ENOENT` of a missing path in `unix`.

The `exception` tool is C++: it throws and catches C++ exceptions on coroutine stacks, and on Windows also
raises and catches SEH exceptions there. Windows builds C++ exceptions on SEH, which rejects frames outside
the stack bounds in the TIB, so this works only because ST switches those bounds with each coroutine stack.

## Linux: Coverage

> Note: We use [Google test](https://github.com/google/googletest/releases/tag/release-1.11.0) in `utest/gtest-fit`.
Expand Down
Loading
Loading