Skip to content

Commit f0eeb85

Browse files
authored
Merge pull request #11 from zombocoder/feature/windows-support
feat(windows): add full Windows/MSVC support
2 parents 76d201d + 2712be4 commit f0eeb85

40 files changed

Lines changed: 992 additions & 320 deletions

.github/workflows/ci.yml

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
os: [ubuntu-latest, macos-latest]
14+
os: [ubuntu-latest, macos-latest, windows-latest]
1515
build_type: [Debug, Release]
1616
include:
1717
- os: ubuntu-latest
@@ -20,49 +20,68 @@ jobs:
2020
- os: macos-latest
2121
cc: clang
2222
cxx: clang++
23+
- os: windows-latest
24+
cc: cl
25+
cxx: cl
2326

2427
runs-on: ${{ matrix.os }}
2528

2629
steps:
2730
- name: Checkout code
2831
uses: actions/checkout@v4
2932

33+
- name: Set up C environment (non-Linux)
34+
if: runner.os != 'Linux'
35+
uses: aminya/setup-cpp@v1
36+
with:
37+
compiler: ${{ runner.os == 'Windows' && 'msvc' || 'clang' }}
38+
vcvarsall: ${{ runner.os == 'Windows' }}
39+
cmake: true
40+
ninja: true
41+
3042
- name: Install dependencies (Ubuntu)
31-
if: matrix.os == 'ubuntu-latest'
43+
if: runner.os == 'Linux'
3244
run: |
3345
sudo apt-get update
34-
sudo apt-get install -y build-essential cmake clang-format clang-tidy libzstd-dev libsodium-dev
46+
sudo apt-get install -y build-essential cmake ninja-build clang-format clang-tidy libzstd-dev libsodium-dev
3547
3648
- name: Install dependencies (macOS)
37-
if: matrix.os == 'macos-latest'
49+
if: runner.os == 'macOS'
3850
run: |
39-
brew install clang-format zstd libsodium || true
40-
# cmake is already available on macOS runners
51+
brew install clang-format zstd libsodium ninja || true
4152
42-
- name: Set up environment
53+
- name: Install dependencies (Windows)
54+
if: runner.os == 'Windows'
55+
shell: bash
4356
run: |
44-
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
45-
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV
57+
vcpkg install zstd:x64-windows libsodium:x64-windows
58+
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> "$GITHUB_ENV"
4659
4760
- name: Configure CMake
61+
shell: bash
4862
run: |
63+
TOOLCHAIN_ARG=""
64+
if [ "${{ runner.os }}" == "Windows" ]; then
65+
TOOLCHAIN_ARG="-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DBFC_BUILD_BENCHMARKS=OFF"
66+
fi
4967
cmake -B build \
5068
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
51-
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
52-
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
5369
-DBFC_WITH_ZSTD=ON \
54-
-DBFC_WITH_SODIUM=ON
70+
-DBFC_WITH_SODIUM=ON \
71+
$TOOLCHAIN_ARG
5572
5673
- name: Build
57-
run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
74+
run: cmake --build build --config ${{ matrix.build_type }} -j4
5875

5976
- name: Run tests
6077
if: matrix.build_type == 'Debug'
78+
shell: bash
6179
run: |
6280
cd build
63-
ctest --output-on-failure --parallel $(nproc 2>/dev/null || sysctl -n hw.ncpu)
81+
ctest --output-on-failure -C ${{ matrix.build_type }} --parallel 4
6482
65-
- name: Test CLI functionality
83+
- name: Test CLI functionality (Unix)
84+
if: matrix.os != 'windows-latest'
6685
run: |
6786
# Create test data
6887
mkdir -p test_data
@@ -218,7 +237,50 @@ jobs:
218237
rm -rf test.bfc test_data test_compressed.bfc test_fast.bfc test_balanced.bfc
219238
rm -rf test_encrypted.bfc test_keyfile.bfc test_enc_comp.bfc test.key
220239
240+
- name: Test CLI functionality (Windows)
241+
if: runner.os == 'Windows'
242+
shell: bash
243+
run: |
244+
BFC=$(find build/bin -name "bfc.exe" | head -1)
245+
[ -z "$BFC" ] && { echo "bfc.exe not found"; exit 1; }
246+
247+
mkdir -p test_data/subdir
248+
echo "Hello World" > test_data/hello.txt
249+
echo "Goodbye" > test_data/bye.txt
250+
echo "Nested file" > test_data/subdir/nested.txt
251+
252+
"$BFC" create test.bfc test_data/
253+
"$BFC" list test.bfc
254+
"$BFC" info test.bfc
255+
"$BFC" verify test.bfc
256+
"$BFC" verify --deep test.bfc
257+
258+
"$BFC" create -c zstd test_compressed.bfc test_data/
259+
"$BFC" info test_compressed.bfc test_data/hello.txt
260+
"$BFC" verify test_compressed.bfc
261+
262+
mkdir extract_test && cd extract_test
263+
"$OLDPWD/$BFC" extract ../test.bfc
264+
[ -f hello.txt ] && echo "hello.txt extracted"
265+
[ -f bye.txt ] && echo "bye.txt extracted"
266+
[ -f subdir/nested.txt ] && echo "nested.txt extracted"
267+
cd ..
268+
269+
"$BFC" create -e testpassword123 test_encrypted.bfc test_data/
270+
mkdir extract_enc && cd extract_enc
271+
"$OLDPWD/$BFC" extract -p testpassword123 ../test_encrypted.bfc
272+
[ -f hello.txt ] && echo "hello.txt extracted from encrypted container"
273+
cd ..
274+
275+
mkdir extract_fail && cd extract_fail
276+
"$OLDPWD/$BFC" extract -p wrongpassword ../test_encrypted.bfc 2>&1 && true
277+
[ $? -ne 0 ] && echo "Correctly failed with wrong password" || true
278+
cd ..
279+
280+
rm -rf test_data test.bfc test_compressed.bfc test_encrypted.bfc extract_enc extract_fail
281+
221282
- name: Run benchmarks
283+
if: matrix.os != 'windows-latest'
222284
run: |
223285
cd build/benchmarks
224286
./benchmark_crc32c

.github/workflows/release.yml

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ jobs:
2929
cc: clang
3030
cxx: clang++
3131
platform: macos
32+
- os: windows-latest
33+
arch: x86_64
34+
cc: cl
35+
cxx: cl
36+
platform: windows
3237

3338
runs-on: ${{ matrix.os }}
3439

@@ -51,7 +56,14 @@ jobs:
5156
# Install create-dmg for DMG creation, zstd for compression, and libsodium for encryption
5257
brew install create-dmg zstd libsodium
5358
54-
- name: Build Release
59+
- name: Install dependencies (Windows)
60+
if: matrix.platform == 'windows'
61+
run: |
62+
vcpkg install zstd:x64-windows libsodium:x64-windows
63+
echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" >> $env:GITHUB_ENV
64+
65+
- name: Build Release (non-Windows)
66+
if: matrix.platform != 'windows'
5567
env:
5668
CC: ${{ matrix.cc }}
5769
CXX: ${{ matrix.cxx }}
@@ -66,12 +78,32 @@ jobs:
6678
6779
cmake --build build --config Release -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)
6880
69-
- name: Run tests
81+
- name: Build Release (Windows)
82+
if: matrix.platform == 'windows'
83+
run: |
84+
cmake -B build `
85+
-DCMAKE_BUILD_TYPE=Release `
86+
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" `
87+
-DVCPKG_TARGET_TRIPLET=x64-windows `
88+
-DBFC_WITH_ZSTD=ON `
89+
-DBFC_WITH_SODIUM=ON `
90+
-DBFC_BUILD_BENCHMARKS=OFF
91+
cmake --build build --config Release -j4
92+
93+
- name: Run tests (non-Windows)
94+
if: matrix.platform != 'windows'
7095
run: |
7196
cd build
7297
ctest --output-on-failure
7398
74-
- name: Test CLI functionality
99+
- name: Run tests (Windows)
100+
if: matrix.platform == 'windows'
101+
run: |
102+
cd build
103+
ctest --output-on-failure -C Release
104+
105+
- name: Test CLI functionality (non-Windows)
106+
if: matrix.platform != 'windows'
75107
run: |
76108
# Create test data
77109
mkdir -p test_data
@@ -158,11 +190,50 @@ jobs:
158190
rm -rf test.bfc test_data test_compressed.bfc test_fast.bfc test_balanced.bfc
159191
rm -rf test_encrypted.bfc test_keyfile.bfc test_enc_comp.bfc test.key
160192
193+
- name: Test CLI functionality (Windows)
194+
if: matrix.platform == 'windows'
195+
shell: pwsh
196+
run: |
197+
New-Item -ItemType Directory -Force test_data\subdir | Out-Null
198+
"Hello World" | Out-File -Encoding utf8 test_data\hello.txt
199+
"Goodbye" | Out-File -Encoding utf8 test_data\bye.txt
200+
"Nested file" | Out-File -Encoding utf8 test_data\subdir\nested.txt
201+
202+
$bfc = Get-ChildItem -Recurse build\bin -Filter bfc.exe | Select-Object -First 1 -ExpandProperty FullName
203+
if (-not $bfc) { Write-Error "bfc.exe not found"; exit 1 }
204+
205+
& $bfc create test.bfc test_data\
206+
& $bfc list test.bfc
207+
& $bfc info test.bfc
208+
& $bfc verify test.bfc
209+
& $bfc verify --deep test.bfc
210+
211+
& $bfc create -c zstd test_compressed.bfc test_data\
212+
& $bfc verify test_compressed.bfc
213+
214+
New-Item -ItemType Directory -Force extract_test | Out-Null
215+
Push-Location extract_test
216+
& $bfc extract ..\test.bfc
217+
if (Test-Path hello.txt) { Write-Output "hello.txt extracted" }
218+
Pop-Location
219+
Remove-Item -Recurse -Force extract_test
220+
221+
& $bfc create -e testpassword123 test_encrypted.bfc test_data\
222+
New-Item -ItemType Directory -Force extract_enc | Out-Null
223+
Push-Location extract_enc
224+
& $bfc extract -p testpassword123 ..\test_encrypted.bfc
225+
if (Test-Path hello.txt) { Write-Output "hello.txt extracted from encrypted container" }
226+
Pop-Location
227+
Remove-Item -Recurse -Force extract_enc
228+
229+
Remove-Item -Recurse -Force test_data, test.bfc, test_compressed.bfc, test_encrypted.bfc -ErrorAction SilentlyContinue
230+
161231
- name: Get version
162232
id: get_version
163233
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
164234

165-
- name: Create release package
235+
- name: Create release package (non-Windows)
236+
if: matrix.platform != 'windows'
166237
run: |
167238
VERSION=${{ steps.get_version.outputs.version }}
168239
PACKAGE_NAME=bfc-${VERSION#v}-${{ matrix.platform }}-${{ matrix.arch }}
@@ -216,6 +287,42 @@ jobs:
216287
# Create tarball
217288
tar -czf ${PACKAGE_NAME}.tar.gz ${PACKAGE_NAME}
218289
290+
- name: Create release package (Windows)
291+
if: matrix.platform == 'windows'
292+
shell: pwsh
293+
run: |
294+
$version = "${{ steps.get_version.outputs.version }}"
295+
$versionNoV = $version.TrimStart('v')
296+
$pkgName = "bfc-$versionNoV-windows-x86_64"
297+
298+
New-Item -ItemType Directory -Force $pkgName | Out-Null
299+
300+
# Find and copy binaries
301+
$bfcExe = Get-ChildItem -Recurse build\bin -Filter bfc.exe | Select-Object -First 1 -ExpandProperty FullName
302+
Copy-Item $bfcExe "$pkgName\bfc.exe"
303+
Copy-Item (Get-ChildItem -Recurse build\lib -Filter bfc.lib | Select-Object -First 1 -ExpandProperty FullName) "$pkgName\bfc.lib"
304+
Copy-Item (Get-ChildItem -Recurse build\lib -Filter bfc.dll -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName) "$pkgName\bfc.dll" -ErrorAction SilentlyContinue
305+
306+
# Copy headers and docs
307+
Copy-Item include\bfc.h "$pkgName\"
308+
Copy-Item README.md "$pkgName\"
309+
Copy-Item LICENSE "$pkgName\"
310+
311+
# Create install script
312+
@'
313+
@echo off
314+
echo Installing BFC...
315+
copy bfc.exe "%ProgramFiles%\bfc\bfc.exe" 2>nul || (
316+
mkdir "%ProgramFiles%\bfc"
317+
copy bfc.exe "%ProgramFiles%\bfc\bfc.exe"
318+
)
319+
copy bfc.h "%ProgramFiles%\bfc\bfc.h"
320+
echo BFC installed to %ProgramFiles%\bfc
321+
'@ | Out-File -Encoding ascii "$pkgName\install.bat"
322+
323+
# Create ZIP
324+
Compress-Archive -Path $pkgName -DestinationPath "$pkgName.zip"
325+
219326
- name: Create DEB and RPM packages (Linux only)
220327
if: matrix.platform == 'linux'
221328
run: |

CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,17 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
3939
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
4040
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0 -fsanitize=address,undefined")
4141
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -DNDEBUG")
42-
42+
4343
if(BFC_COVERAGE)
4444
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
4545
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
4646
endif()
47+
elseif(MSVC)
48+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX /wd4996")
49+
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od /Zi /RTC1")
50+
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O2 /DNDEBUG")
51+
# Disable sanitizers on MSVC (not supported the same way)
52+
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
4753
endif()
4854

4955
# Find dependencies

README.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A high-performance, single-file container format for storing files and directori
1515
- **Optional compression** - ZSTD compression with intelligent content analysis
1616
- **Optional encryption** - ChaCha20-Poly1305 AEAD with Argon2id key derivation
1717
- **Integrity validation** - CRC32C checksums with hardware acceleration
18-
- **Cross-platform** - Works on Linux, macOS, FreeBSD, and other Unix systems
18+
- **Cross-platform** - Works on Linux, macOS, FreeBSD, and Windows (MSVC/MinGW-w64)
1919
- **Crash-safe writes** - Atomic container creation with index at EOF
2020
- **Memory efficient** - Optimized for large containers and small memory footprint
2121

@@ -46,14 +46,14 @@ cmake --build build
4646

4747
### Prerequisites
4848

49-
- C17 compatible compiler (GCC 7+, Clang 6+)
49+
- C17 compatible compiler (GCC 7+, Clang 6+, or MSVC 2019+)
5050
- CMake 3.15+
51-
- POSIX-compliant system
5251

5352
**Optional dependencies:**
5453
- ZSTD library for compression support
5554
- libsodium for encryption support
56-
- pkg-config (or pkgconf on FreeBSD) for dependency detection
55+
- pkg-config (or pkgconf on FreeBSD/Linux) for dependency detection on Unix
56+
- vcpkg for dependency management on Windows
5757

5858
### Build from source
5959

@@ -87,6 +87,32 @@ cmake -B build -DCMAKE_BUILD_TYPE=Release -DBFC_WITH_ZSTD=ON -DBFC_WITH_SODIUM=O
8787
make -C build
8888
```
8989

90+
**Windows (MSVC) setup:**
91+
92+
```powershell
93+
# Install dependencies via vcpkg
94+
vcpkg install zstd:x64-windows libsodium:x64-windows
95+
96+
# Configure with vcpkg toolchain
97+
cmake -B build `
98+
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
99+
-DVCPKG_TARGET_TRIPLET=x64-windows `
100+
-DBFC_WITH_ZSTD=ON `
101+
-DBFC_WITH_SODIUM=ON
102+
103+
# Build
104+
cmake --build build --config Release
105+
106+
# Run
107+
.\build\bin\Release\bfc.exe create archive.bfc path\to\files\
108+
```
109+
110+
> **Windows notes:**
111+
> - Symlink creation requires Developer Mode or elevated privileges; symlinks stored in
112+
> containers are extracted as regular files on Windows without Developer Mode.
113+
> - FUSE mount (`BFC_WITH_FUSE`) is not supported on Windows.
114+
> - MinGW-w64 is also supported; use the standard Unix cmake/make flow with the MinGW generator.
115+
90116
### Build options
91117

92118
```bash

0 commit comments

Comments
 (0)