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
13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ vgcore.*
dbg*
diag*

.env.secret
.env.secret

vs2022/.vs
vs2022/Release/
vs2022/Debug/
vs2022/x64/Release/
vs2022/x64/Debug/
vs2022/x86/Release/
vs2022/x86/Debug/

*.vcxproj.user
*.sln.docstates
81 changes: 35 additions & 46 deletions Makefile.windows
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
# Makefile.windows — VoidCache build for Windows (MSYS2 / UCRT64)
# Makefile.windows — VoidCache build for Windows (MSYS2 UCRT64)
#
# Open in MSYS2 UCRT64 terminal and run:
# make -f Makefile.windows
# make -f Makefile.windows test
# make -f Makefile.windows smoke
# IMPORTANT: Open the "MSYS2 UCRT64" terminal (not MSYS2, not MinGW, not Cygwin)
# You can find it in Start Menu → "MSYS2 UCRT64"
#
# Prerequisites (install once):
# pacman -S mingw-w64-ucrt-x86_64-gcc \
# mingw-w64-ucrt-x86_64-openssl \
# mingw-w64-ucrt-x86_64-wepoll \
# make
# Install deps once:
# pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-openssl make
#
# Build:
# make -f Makefile.windows vcli
#
# Note: wepoll and mman are bundled in compat/ — no pacman packages needed.
# ─────────────────────────────────────────────────────────────────────────────

CC := gcc
CFLAGS := -O2 -std=c11 \
-Iinclude -Inet -Icompat \
-I$(MSYSTEM_PREFIX)/include \
-D_WIN32_WINNT=0x0A00 \
-DVCACHE_WINDOWS \
-Wall -Wextra \
-Wno-unused-function -Wno-unused-parameter

# OpenSSL from MSYS2 pacman
OPENSSL_PREFIX := $(MSYSTEM_PREFIX)
CFLAGS += -I$(OPENSSL_PREFIX)/include

LDFLAGS := -L$(OPENSSL_PREFIX)/lib \
LDFLAGS := -L$(MSYSTEM_PREFIX)/lib \
-lssl -lcrypto \
-lpthread \
-lws2_32 -lbcrypt \
Expand All @@ -33,73 +29,66 @@ LDFLAGS := -L$(OPENSSL_PREFIX)/lib \
CORE_SRC := src/voidcache.c
NET_SRC := net/proto.c net/auth.c net/commands.c net/server.c net/cluster.c
CLI_SRC := cli/vcli.c
COMPAT_SRC := compat/wepoll.c compat/mman.c

TEST_SRC := tests/test_voidcache.c
BENCH_SRC := bench/benchmark.c

TARGET := vcli.exe
TEST_BIN := voidcache_test.exe
BENCH_BIN := voidcache_bench.exe

.PHONY: all vcli test bench smoke clean deps
.PHONY: all vcli test bench smoke clean deps bundle

all: vcli test bench
all: vcli

# ── Install prerequisites ──────────────────────────────────────────────────
deps:
pacman -S --noconfirm --needed \
mingw-w64-ucrt-x86_64-gcc \
mingw-w64-ucrt-x86_64-openssl \
mingw-w64-ucrt-x86_64-wepoll \
make
@echo "Dependencies installed. Run: make -f Makefile.windows"
@echo "Done. Now run: make -f Makefile.windows vcli"

# ── Main binary ────────────────────────────────────────────────────────────
vcli: $(CORE_SRC) $(NET_SRC) $(CLI_SRC)
# ── Main binary (wepoll.c + mman.c compiled inline, no extra libs needed) ──
vcli: $(CORE_SRC) $(NET_SRC) $(CLI_SRC) $(COMPAT_SRC)
$(CC) $(CFLAGS) $^ -o $(TARGET) $(LDFLAGS)
@echo "Built: $(TARGET)"

# ── Tests (no network layer) ───────────────────────────────────────────────
$(TEST_BIN): $(CORE_SRC) $(TEST_SRC)
# ── Tests (core only, no network) ─────────────────────────────────────────
$(TEST_BIN): $(CORE_SRC) $(TEST_SRC) compat/mman.c
$(CC) $(CFLAGS) $^ -o $@ -lpthread -lm
@echo "Built: $(TEST_BIN)"

test: $(TEST_BIN)
./$(TEST_BIN)

# ── Benchmark ─────────────────────────────────────────────────────────────
$(BENCH_BIN): $(CORE_SRC) $(BENCH_SRC)
$(BENCH_BIN): $(CORE_SRC) $(BENCH_SRC) compat/mman.c
$(CC) $(CFLAGS) $^ -o $@ -lpthread -lm
@echo "Built: $(BENCH_BIN)"

bench: $(BENCH_BIN)
./$(BENCH_BIN)

# ── Smoke test ─────────────────────────────────────────────────────────────
# ── Quick smoke test ───────────────────────────────────────────────────────
smoke: vcli
@echo "Starting server on :16399..."
./$(TARGET) server --port 16399 &
start "" ./$(TARGET) server --port 16399
sleep 1
@echo "--- PING ---"
./$(TARGET) -p 16399 --no-color PING
@echo "--- SET/GET ---"
./$(TARGET) -p 16399 --no-color SET hello world
./$(TARGET) -p 16399 --no-color GET hello
@echo "--- VCSET int ---"
./$(TARGET) -p 16399 --no-color VCSET score int 42
./$(TARGET) -p 16399 --no-color VCGET score
@echo "Stopping server..."
./$(TARGET) -p 16399 --no-color SHUTDOWN NOSAVE 2>/dev/null || true
./$(TARGET) -p 16399 --no-color SHUTDOWN NOSAVE 2>nul || true

clean:
rm -f $(TARGET) $(TEST_BIN) $(BENCH_BIN) *.exe

# ── Copy OpenSSL DLLs next to the binary (needed to run outside MSYS2) ──────
# ── Bundle DLLs for standalone use ────────────────────────────────────────
bundle:
@echo "Copying OpenSSL DLLs for standalone distribution..."
cp $(OPENSSL_PREFIX)/bin/libssl-3-x64.dll . 2>/dev/null || \
cp $(OPENSSL_PREFIX)/bin/libssl*.dll . 2>/dev/null || true
cp $(OPENSSL_PREFIX)/bin/libcrypto-3-x64.dll . 2>/dev/null || \
cp $(OPENSSL_PREFIX)/bin/libcrypto*.dll . 2>/dev/null || true
cp $(OPENSSL_PREFIX)/bin/libgcc_s_seh-1.dll . 2>/dev/null || true
cp $(OPENSSL_PREFIX)/bin/libwinpthread-1.dll . 2>/dev/null || true
@echo "DLLs copied. You can now run vcli.exe from any folder."
@for dll in libssl-3-x64.dll libcrypto-3-x64.dll \
libgcc_s_seh-1.dll libwinpthread-1.dll; do \
cp "$(MSYSTEM_PREFIX)/bin/$$dll" . 2>/dev/null && \
echo " Copied $$dll" || true; \
done
@echo "DLLs bundled. vcli.exe runs standalone."

clean:
rm -f $(TARGET) $(TEST_BIN) $(BENCH_BIN)
139 changes: 139 additions & 0 deletions build-windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# build-windows.ps1 — Build vcli.exe on Windows using MSYS2 UCRT64
#
# Run from PowerShell (as normal user, NOT Administrator):
# Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
# .\build-windows.ps1

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

$MSYS2_DIR = "C:\msys64"
$UCRT64_GCC = "$MSYS2_DIR\ucrt64\bin\gcc.exe"
$UCRT64_BIN = "$MSYS2_DIR\ucrt64\bin"
$PACMAN = "$MSYS2_DIR\usr\bin\pacman.exe"
# Use MSYS2's own bash explicitly — NOT any other bash on PATH (e.g. Cygwin, Git)
$MSYS2_BASH = "$MSYS2_DIR\usr\bin\bash.exe"

Write-Host ""
Write-Host "=== VoidCache Windows Build ===" -ForegroundColor Cyan
Write-Host ""

# ── Step 1: Check MSYS2 ───────────────────────────────────────────────────────
if (-not (Test-Path $MSYS2_BASH)) {
Write-Host "[1/4] MSYS2 not found at $MSYS2_DIR. Installing via winget..." -ForegroundColor Yellow
$winget = Get-Command winget -ErrorAction SilentlyContinue
if (-not $winget) {
Write-Host "ERROR: winget not found. Install from https://aka.ms/getwinget" -ForegroundColor Red
Write-Host "Or install MSYS2 manually from https://www.msys2.org/ to C:\msys64" -ForegroundColor Red
exit 1
}
winget install --id MSYS2.MSYS2 --silent --accept-package-agreements --accept-source-agreements
Start-Sleep -Seconds 5
if (-not (Test-Path $MSYS2_BASH)) {
Write-Host "ERROR: MSYS2 install failed or not at C:\msys64" -ForegroundColor Red
exit 1
}
}
Write-Host "[1/4] MSYS2 found at $MSYS2_DIR" -ForegroundColor Green

# ── Step 2: Install UCRT64 gcc + openssl via pacman ───────────────────────────
Write-Host "[2/4] Installing UCRT64 gcc and OpenSSL (wepoll+mman are bundled)..." -ForegroundColor Yellow

# Run pacman through MSYS2's OWN bash with --login to get the right environment
# CRITICAL: use $MSYS2_BASH explicitly, never rely on PATH-resolved bash
$packages = "mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-openssl make"
$pacmanCmd = "pacman -S --noconfirm --needed $packages"
& $MSYS2_BASH --login -c $pacmanCmd
if ($LASTEXITCODE -ne 0) {
Write-Host "WARNING: pacman reported errors (may be harmless if packages already installed)" -ForegroundColor Yellow
}
Write-Host "[2/4] Packages ready." -ForegroundColor Green

# ── Step 3: Verify we have the RIGHT gcc (UCRT64, not Cygwin) ────────────────
if (-not (Test-Path $UCRT64_GCC)) {
Write-Host "ERROR: UCRT64 gcc not found at $UCRT64_GCC" -ForegroundColor Red
Write-Host "Run manually in MSYS2 UCRT64 terminal: pacman -S mingw-w64-ucrt-x86_64-gcc" -ForegroundColor Red
exit 1
}
$gccVersion = & $UCRT64_GCC --version 2>&1 | Select-Object -First 1
Write-Host "[3/4] Compiler: $gccVersion" -ForegroundColor Green

# ── Step 4: Build directly with UCRT64 gcc — no bash, no make, no PATH issues ─
Write-Host "[4/4] Building vcli.exe..." -ForegroundColor Yellow

$SRC = Split-Path -Parent $MyInvocation.MyCommand.Path
$OPENSSL = "$MSYS2_DIR\ucrt64"

$Sources = @(
"src\voidcache.c",
"net\proto.c",
"net\auth.c",
"net\commands.c",
"net\server.c",
"net\cluster.c",
"cli\vcli.c",
"compat\wepoll.c",
"compat\mman.c"
) | ForEach-Object { Join-Path $SRC $_ }

$Flags = @(
"-O2", "-std=c11",
"-Iinclude", "-Inet", "-Icompat",
"-I$OPENSSL\include",
"-D_WIN32_WINNT=0x0A00",
"-DVCACHE_WINDOWS",
"-Wno-unused-function", "-Wno-unused-parameter"
)

$Libs = @(
"-L$OPENSSL\lib",
"-lssl", "-lcrypto",
"-lpthread",
"-lws2_32", "-lbcrypt",
"-lm"
)

$OutExe = Join-Path $SRC "vcli.exe"

$GccArgs = $Flags + $Sources + @("-o", $OutExe) + $Libs

Write-Host " $UCRT64_GCC $($GccArgs -join ' ')" -ForegroundColor DarkGray
Write-Host ""

& $UCRT64_GCC @GccArgs
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "Build FAILED. See errors above." -ForegroundColor Red
exit 1
}

# ── Copy required DLLs next to the binary ────────────────────────────────────
Write-Host ""
Write-Host "Copying runtime DLLs..." -ForegroundColor Yellow

$dlls = @(
"libssl-3-x64.dll",
"libcrypto-3-x64.dll",
"libgcc_s_seh-1.dll",
"libwinpthread-1.dll",
"libstdc++-6.dll"
)
foreach ($dll in $dlls) {
$src = Join-Path $UCRT64_BIN $dll
if (Test-Path $src) {
Copy-Item $src $SRC -Force
Write-Host " Copied $dll" -ForegroundColor DarkGray
}
}

Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " Build complete! vcli.exe is ready." -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host "Test (cluster must be running):" -ForegroundColor White
Write-Host " .\vcli.exe -h localhost -p 6379 PING" -ForegroundColor Cyan
Write-Host ""
Write-Host "Interactive shell:" -ForegroundColor White
Write-Host " .\vcli.exe -h localhost -p 6379" -ForegroundColor Cyan
Write-Host ""
15 changes: 14 additions & 1 deletion cli/vcli.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
* --pipe read commands from stdin (batch mode)
* --raw print raw bytes, no type decoration
*/
#define _POSIX_C_SOURCE 200809L
#ifndef _WIN32
# define _POSIX_C_SOURCE 200809L
#endif
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -38,6 +40,11 @@
#include <signal.h>
#include <inttypes.h>

#ifdef _MSC_VER
# include "../compat/msvc.h"
#elif defined(_WIN32)
# include "../compat/windows.h"
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
Expand Down Expand Up @@ -555,6 +562,12 @@ static size_t parse_mem(const char *s) {

int main(int argc, char **argv) {
if (!isatty(STDOUT_FILENO)) use_color = false;

#ifdef _WIN32
/* Winsock must be initialised before any socket operations on Windows. */
{ WSADATA _wsa; WSAStartup(MAKEWORD(2,2), &_wsa); }
#endif

signal(SIGPIPE, SIG_IGN);

/* Defaults */
Expand Down
Loading
Loading