Skip to content

Commit 605cc1b

Browse files
authored
Merge pull request #9 from mondain/feature/windows-build
Add Windows build support
2 parents fd553aa + 48b6ce4 commit 605cc1b

5 files changed

Lines changed: 208 additions & 41 deletions

File tree

.github/workflows/ci.yml

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
os:
1818
- ubuntu-latest
1919
- macos-latest
20+
- windows-latest
2021

2122
steps:
2223
- name: Checkout
@@ -38,19 +39,67 @@ jobs:
3839
submodules: recursive
3940

4041
- name: Show toolchain
42+
shell: bash
4143
run: |
4244
cmake --version
43-
c++ --version
45+
if command -v c++ >/dev/null 2>&1; then c++ --version; fi
46+
if command -v cl >/dev/null 2>&1; then cl; fi
47+
48+
- name: Set up Windows dependencies
49+
if: runner.os == 'Windows'
50+
shell: pwsh
51+
run: |
52+
# picotls requires pkg-config at configure time (even on Windows where
53+
# brotli is absent); install the lightweight pkgconfiglite shim.
54+
choco install pkgconfiglite --no-progress -y
55+
56+
$candidates = @(
57+
"C:\Program Files\OpenSSL",
58+
"C:\Program Files\OpenSSL-Win64",
59+
"C:\OpenSSL-Win64"
60+
)
61+
$opensslFound = $false
62+
foreach ($candidate in $candidates) {
63+
if (Test-Path "$candidate\include\openssl\ssl.h") {
64+
"OPENSSL_ROOT_DIR=$candidate" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
65+
Write-Host "OpenSSL found at $candidate"
66+
$opensslFound = $true
67+
break
68+
}
69+
}
70+
if (-not $opensslFound) {
71+
choco install openssl --no-progress -y
72+
foreach ($candidate in $candidates) {
73+
if (Test-Path "$candidate\include\openssl\ssl.h") {
74+
"OPENSSL_ROOT_DIR=$candidate" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
75+
Write-Host "OpenSSL installed at $candidate"
76+
break
77+
}
78+
}
79+
}
4480
4581
- name: Configure
46-
run: >
47-
cmake -S . -B build
48-
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
49-
-DOPENMOQ_PICOQUIC_SOURCE_DIR="${{ github.workspace }}/third_party/picoquic"
50-
-DOPENMOQ_PICOTLS_SOURCE_DIR="${{ github.workspace }}/third_party/picotls"
82+
shell: bash
83+
run: |
84+
args=(
85+
cmake -S . -B build
86+
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
87+
"-DOPENMOQ_PICOQUIC_SOURCE_DIR=${{ github.workspace }}/third_party/picoquic"
88+
"-DOPENMOQ_PICOTLS_SOURCE_DIR=${{ github.workspace }}/third_party/picotls"
89+
)
90+
if [ -n "${OPENSSL_ROOT_DIR:-}" ]; then
91+
args+=("-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}")
92+
fi
93+
"${args[@]}"
5194
5295
- name: Build
5396
run: cmake --build build --parallel
5497

5598
- name: Test
56-
run: ctest --test-dir build --output-on-failure
99+
shell: bash
100+
run: |
101+
if [ "${{ runner.os }}" = "Windows" ]; then
102+
ctest --test-dir build -C Debug --output-on-failure
103+
else
104+
ctest --test-dir build --output-on-failure
105+
fi

.github/workflows/release.yml

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
os:
2626
- ubuntu-latest
2727
- macos-latest
28+
- windows-latest
2829

2930
steps:
3031
- name: Checkout
@@ -45,14 +46,54 @@ jobs:
4546
path: third_party/picotls
4647
submodules: recursive
4748

49+
- name: Set up Windows dependencies
50+
if: runner.os == 'Windows'
51+
shell: pwsh
52+
run: |
53+
# picotls requires pkg-config at configure time (even on Windows where
54+
# brotli is absent); install the lightweight pkgconfiglite shim.
55+
choco install pkgconfiglite --no-progress -y
56+
57+
$candidates = @(
58+
"C:\Program Files\OpenSSL",
59+
"C:\Program Files\OpenSSL-Win64",
60+
"C:\OpenSSL-Win64"
61+
)
62+
$opensslFound = $false
63+
foreach ($candidate in $candidates) {
64+
if (Test-Path "$candidate\include\openssl\ssl.h") {
65+
"OPENSSL_ROOT_DIR=$candidate" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
66+
Write-Host "OpenSSL found at $candidate"
67+
$opensslFound = $true
68+
break
69+
}
70+
}
71+
if (-not $opensslFound) {
72+
choco install openssl --no-progress -y
73+
foreach ($candidate in $candidates) {
74+
if (Test-Path "$candidate\include\openssl\ssl.h") {
75+
"OPENSSL_ROOT_DIR=$candidate" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
76+
Write-Host "OpenSSL installed at $candidate"
77+
break
78+
}
79+
}
80+
}
81+
4882
- name: Configure
49-
run: >
50-
cmake -S . -B build
51-
-DCMAKE_BUILD_TYPE=Release
52-
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
53-
-DOPENMOQ_PICOQUIC_SOURCE_DIR="${{ github.workspace }}/third_party/picoquic"
54-
-DOPENMOQ_PICOTLS_SOURCE_DIR="${{ github.workspace }}/third_party/picotls"
55-
-DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
83+
shell: bash
84+
run: |
85+
args=(
86+
cmake -S . -B build
87+
-DCMAKE_BUILD_TYPE=Release
88+
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
89+
"-DOPENMOQ_PICOQUIC_SOURCE_DIR=${{ github.workspace }}/third_party/picoquic"
90+
"-DOPENMOQ_PICOTLS_SOURCE_DIR=${{ github.workspace }}/third_party/picotls"
91+
-DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
92+
)
93+
if [ -n "${OPENSSL_ROOT_DIR:-}" ]; then
94+
args+=("-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}")
95+
fi
96+
"${args[@]}"
5697
5798
- name: Build
5899
run: cmake --build build --config Release --parallel
@@ -71,12 +112,22 @@ jobs:
71112
72113
package_root="openmoq-publisher-${version}-${RUNNER_OS}"
73114
mkdir -p "${package_root}"
74-
cp build/openmoq-publisher "${package_root}/"
75-
cp README.md LICENSE "${package_root}/"
76-
cp -R docs "${package_root}/docs"
77115
78-
archive="${package_root}.tar.gz"
79-
tar -czf "${archive}" "${package_root}"
116+
if [[ "${RUNNER_OS}" == "Windows" ]]; then
117+
# MSVC multi-config generator places the binary under build/Release/
118+
cp build/Release/openmoq-publisher.exe "${package_root}/"
119+
cp README.md LICENSE "${package_root}/"
120+
cp -R docs "${package_root}/docs"
121+
archive="${package_root}.zip"
122+
7z a "${archive}" "${package_root}"
123+
else
124+
cp build/openmoq-publisher "${package_root}/"
125+
cp README.md LICENSE "${package_root}/"
126+
cp -R docs "${package_root}/docs"
127+
archive="${package_root}.tar.gz"
128+
tar -czf "${archive}" "${package_root}"
129+
fi
130+
80131
if [[ "${version}" == v* ]]; then
81132
echo "release_enabled=true" >> "${GITHUB_ENV}"
82133
else

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ moqxr.code-workspace
2626
run.log
2727
run-trace*.log
2828
openmoq-publisher-trace.csv
29+
/.claude
30+
/third_party

CMakeLists.txt

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ option(OPENMOQ_BUILD_TESTS "Build OpenMOQ publisher tests" ON)
1313
option(OPENMOQ_ENABLE_PICOQUIC "Enable picoquic transport integration when picoquic is available" ON)
1414
option(OPENMOQ_RUN_PICOQUIC_SMOKE_TESTS "Build and run picoquic loopback smoke tests" OFF)
1515

16-
set(OPENMOQ_PICOQUIC_SOURCE_DIR "/media/mondain/terrorbyte/workspace/github/picoquic" CACHE PATH
16+
set(OPENMOQ_PICOQUIC_SOURCE_DIR "" CACHE PATH
1717
"Path to a picoquic source checkout")
1818

1919
set(OPENMOQ_HAS_PICOQUIC OFF)
@@ -73,6 +73,41 @@ if(OPENMOQ_ENABLE_PICOQUIC AND EXISTS "${OPENMOQ_PICOQUIC_SOURCE_DIR}/CMakeLists
7373
# directories list when Brotli is discovered via pkg-config. CMake on
7474
# macOS rejects those malformed source-prefixed paths during generate.
7575
openmoq_sanitize_target_link_directories(picotls-core)
76+
if(WIN32)
77+
# picotls's cli, bench, and test executables use POSIX headers not available
78+
# on Windows. Exclude them from the default build; the libraries we need
79+
# (picotls-core, picotls-openssl, picotls-fusion) are unaffected.
80+
foreach(_picotls_exe IN ITEMS
81+
cli
82+
test-openssl.t
83+
test-minicrypto.t
84+
test-fusion.t
85+
test-mbedtls.t
86+
ptlsbench
87+
fuzz-asn1
88+
fuzz-server-hello
89+
fuzz-client-hello)
90+
if(TARGET "${_picotls_exe}")
91+
set_target_properties("${_picotls_exe}" PROPERTIES EXCLUDE_FROM_ALL ON)
92+
endif()
93+
endforeach()
94+
# picotls.h includes "wincompat.h" on Windows but picotls's own CMakeLists.txt
95+
# does not add picotlsvs/picotls to picotls-core's include path.
96+
if(TARGET picotls-core AND EXISTS "${OPENMOQ_PICOTLS_SOURCE_DIR}/picotlsvs/picotls")
97+
target_include_directories(picotls-core PRIVATE
98+
"${OPENMOQ_PICOTLS_SOURCE_DIR}/picotlsvs/picotls")
99+
endif()
100+
# picotls-core calls wintimeofday() which is only compiled inside the VS
101+
# project files; add it explicitly for CMake Windows builds.
102+
if(TARGET picotls-core AND EXISTS "${OPENMOQ_PICOTLS_SOURCE_DIR}/picotlsvs/picotls/wintimeofday.c")
103+
target_sources(picotls-core PRIVATE
104+
"${OPENMOQ_PICOTLS_SOURCE_DIR}/picotlsvs/picotls/wintimeofday.c")
105+
endif()
106+
# picotls-minicrypto uses the Windows BCrypt API for random bytes.
107+
if(TARGET picotls-minicrypto)
108+
target_link_libraries(picotls-minicrypto bcrypt)
109+
endif()
110+
endif()
76111
set(OPENMOQ_HAS_PICOQUIC ON)
77112
else()
78113
message(STATUS "picoquic checkout found, but picotls source was not found; building without picoquic integration")
@@ -101,20 +136,26 @@ target_compile_features(openmoq_publisher_lib PUBLIC cxx_std_20)
101136

102137
if(OPENMOQ_HAS_PICOQUIC)
103138
target_compile_definitions(openmoq_publisher_lib PRIVATE OPENMOQ_HAS_PICOQUIC=1)
104-
if(TARGET picohttp-core AND TARGET picoquic-log AND NOT APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
139+
if(TARGET picohttp-core AND TARGET picoquic-log AND NOT APPLE AND NOT WIN32 AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
140+
# Linux with modern CMake: RESCAN resolves circular deps between picohttp/picoquic via --start-group/--end-group.
105141
target_link_libraries(openmoq_publisher_lib PRIVATE "$<LINK_GROUP:RESCAN,picohttp-core,picoquic-log,picoquic-core>")
106142
target_include_directories(openmoq_publisher_lib PRIVATE "${OPENMOQ_PICOQUIC_SOURCE_DIR}/picohttp")
107143
else()
108144
target_link_libraries(openmoq_publisher_lib PRIVATE picoquic-core)
109145
endif()
110-
if(TARGET picohttp-core AND (APPLE OR CMAKE_VERSION VERSION_LESS "3.24"))
146+
if(TARGET picohttp-core AND (APPLE OR WIN32 OR CMAKE_VERSION VERSION_LESS "3.24"))
111147
target_link_libraries(openmoq_publisher_lib PRIVATE picohttp-core)
112148
target_include_directories(openmoq_publisher_lib PRIVATE "${OPENMOQ_PICOQUIC_SOURCE_DIR}/picohttp")
113149
endif()
150+
if(WIN32)
151+
target_link_libraries(openmoq_publisher_lib PRIVATE ws2_32 iphlpapi)
152+
endif()
114153
endif()
115154

116155
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
117156
target_compile_options(openmoq_publisher_lib PRIVATE -Wall -Wextra -Wpedantic)
157+
elseif(MSVC)
158+
target_compile_options(openmoq_publisher_lib PRIVATE /W4 /WX- /utf-8)
118159
endif()
119160

120161
add_executable(openmoq-publisher src/main.cpp)

README.md

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OpenMOQ Publisher
22

3-
`moqxr` is a C++20 OpenMOQ publisher contribution project for Linux and macOS.
3+
`moqxr` is a C++20 OpenMOQ publisher contribution project for Linux, macOS, and Windows.
44

55
It packages MP4 input into CMSF-style publishable objects, supports MOQT draft-specific framing for drafts 14 and 16, and can either inspect the generated publish plan locally or publish it over a picoquic-backed transport when local `picoquic` and `picotls` checkouts are available.
66

@@ -42,7 +42,7 @@ This keeps the project aligned with CMAF-style publication while reusing the sam
4242

4343
- `draft-ietf-moq-transport-14` is the primary target
4444
- `draft-ietf-moq-transport-16` is represented as a secondary compatibility profile
45-
- draft-specific assumptions are documented in [docs/protocol-mapping.md](/media/mondain/terrorbyte/workspace/github/moqxr/docs/protocol-mapping.md)
45+
- draft-specific assumptions are documented in [docs/protocol-mapping.md](docs/protocol-mapping.md)
4646

4747
## Repository layout
4848

@@ -51,62 +51,85 @@ This keeps the project aligned with CMAF-style publication while reusing the sam
5151
- `tests`: CTest-based unit coverage
5252
- `docs`: protocol notes and design references
5353
- `docs/transport-plan.md`: picoquic integration plan and implementation checklist
54-
- `.github/workflows/ci.yml`: GitHub Actions build and test workflow for Linux and macOS
55-
- `.github/workflows/release.yml`: GitHub Actions release-build workflow that uploads Linux and macOS archives
54+
- `.github/workflows/ci.yml`: GitHub Actions build and test workflow for Linux, macOS, and Windows
55+
- `.github/workflows/release.yml`: GitHub Actions release-build workflow that uploads Linux, macOS, and Windows archives
5656

5757
## Release builds
5858

59-
For users who just want a prebuilt binary, GitHub Actions publishes release archives for Linux and macOS:
59+
For users who just want a prebuilt binary, GitHub Actions publishes release archives for Linux, macOS, and Windows:
6060

6161
- pushing a `v*` tag builds release artifacts and attaches them to the matching GitHub Release
6262
- running the `Release Builds` workflow manually uploads the same archives as workflow artifacts
6363
- manual runs can also publish a GitHub Release when you provide a `release_tag` such as `v0.1.0`
6464
- both CI and release workflows check out `private-octopus/picoquic` plus `private-octopus/picotls`, so published binaries include the picoquic transport path instead of falling back to a local-inspection-only build
65+
- Linux and macOS archives are `.tar.gz`; Windows archives are `.zip` and contain `openmoq-publisher.exe`
6566

6667
## Build
6768

6869
### Baseline build
6970

70-
This is the default path for local development:
71+
This is the default path for local development. It works on Linux, macOS, and Windows:
7172

7273
```bash
7374
cmake -S . -B build -DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
7475
cmake --build build
7576
ctest --test-dir build --output-on-failure
7677
```
7778

78-
### Build with local picoquic and picotls
79-
80-
If you have local checkouts at:
81-
82-
- `/media/mondain/terrorbyte/workspace/github/picoquic`
83-
- `/media/mondain/terrorbyte/workspace/github/picotls`
79+
On Windows with the Visual Studio generator, the binary lands in `build\Release\` or `build\Debug\` depending on the config passed to `--build`.
8480

85-
then the project will automatically compile against them.
81+
### Build with local picoquic and picotls
8682

87-
Required picotls setup:
83+
Clone picoquic and picotls to any convenient location and initialise the picotls submodules:
8884

8985
```bash
90-
git -C /media/mondain/terrorbyte/workspace/github/picotls submodule update --init --recursive
86+
git clone https://github.com/private-octopus/picoquic.git /path/to/picoquic
87+
git clone --recurse-submodules https://github.com/private-octopus/picotls.git /path/to/picotls
9188
```
9289

93-
Then configure and build normally:
90+
Then point CMake at them:
9491

9592
```bash
96-
cmake -S . -B build -DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
93+
cmake -S . -B build \
94+
-DOPENMOQ_PICOQUIC_SOURCE_DIR=/path/to/picoquic \
95+
-DOPENMOQ_PICOTLS_SOURCE_DIR=/path/to/picotls \
96+
-DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
9797
cmake --build build
9898
ctest --test-dir build --output-on-failure
9999
```
100100

101+
**Windows additional requirements — pkg-config and OpenSSL**
102+
103+
picotls requires both `pkg-config` (to probe for optional brotli) and OpenSSL headers and libraries. On Windows you need to install both and tell CMake where OpenSSL is:
104+
105+
```powershell
106+
# One-time: install pkg-config shim and OpenSSL (skip if already present)
107+
choco install pkgconfiglite openssl
108+
109+
cmake -S . -B build `
110+
-DOPENMOQ_PICOQUIC_SOURCE_DIR=C:\path\to\picoquic `
111+
-DOPENMOQ_PICOTLS_SOURCE_DIR=C:\path\to\picotls `
112+
-DOPENSSL_ROOT_DIR="C:\Program Files\OpenSSL-Win64" `
113+
-DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=OFF
114+
cmake --build build --config Release
115+
ctest --test-dir build -C Release --output-on-failure
116+
```
117+
118+
On Windows, GitHub Actions workflows (including CI and release) set `OPENSSL_ROOT_DIR` automatically from the runner's pre-installed OpenSSL, so no manual step is needed there.
119+
101120
Useful CMake options:
102121

103122
- `-DOPENMOQ_ENABLE_PICOQUIC=ON|OFF`
104123
- `-DOPENMOQ_PICOQUIC_SOURCE_DIR=/path/to/picoquic`
124+
- `-DOPENMOQ_PICOTLS_SOURCE_DIR=/path/to/picotls`
125+
- `-DOPENSSL_ROOT_DIR=/path/to/openssl` (Windows only, when OpenSSL is not on the system path)
105126
- `-DOPENMOQ_RUN_PICOQUIC_SMOKE_TESTS=ON|OFF`
106127

107128
## Quick Start
108129

109-
If you already have a sample MP4 and just want to see what the publisher does, these are the most useful first commands:
130+
If you already have a sample MP4 and just want to see what the publisher does, these are the most useful first commands.
131+
132+
> **Windows note**: replace `./build/openmoq-publisher` with `build\Release\openmoq-publisher.exe` in the examples below. For trace-enabled examples, use `set OPENMOQ_PICOQUIC_TRACE=1` in `cmd.exe` or `$env:OPENMOQ_PICOQUIC_TRACE=1` in PowerShell instead of the shell prefix form.
110133
111134
Inspect the publish plan with the default settings:
112135

@@ -556,8 +579,9 @@ GitHub Actions is configured to build and test the project on:
556579

557580
- `ubuntu-latest`
558581
- `macos-latest`
582+
- `windows-latest`
559583

560-
The workflow runs the same CMake configure, build, and CTest steps on both platforms.
584+
The workflow runs the same CMake configure, build, and CTest steps on all three platforms. On Windows, OpenSSL is located automatically from the runner's pre-installed copy and passed to CMake via `OPENSSL_ROOT_DIR`.
561585

562586
## Transport Notes
563587

0 commit comments

Comments
 (0)