Skip to content

Repository files navigation

opus-packaging

Builds Opus as a shared library (opus.dll + opus.lib import library) on Windows and packages the public headers + binaries into zip files that FreeSWITCH's mod_opus (and mod_opusfile) can link against — replacing the in-tree source build of opus-1.1 that w32\download_opus.props + libs\win32\opus\*.vcxproj do today.

On Linux, those modules build against the distro's libopus-dev. There is no equivalent prebuilt package on Windows, so this repo builds one: it clones a chosen Opus tag, builds it with CMake + MSVC, and ships the result as versioned zips. Publish them to a GitHub Release (or a CDN) and FreeSWITCH's MSBuild props fetches them at build time — the same pattern as libnode-packaging, ffmpeg-packaging and libcodec2-packaging.

Default version: v1.6.1 (the current Opus release).

What it produces

For Opus v1.6.1, building x64 Win32 × Release Debug:

opus-1.6.1-headers.zip                    opus-1.6.1/include/opus/{opus.h, opus_defines.h,
                                                                   opus_multistream.h,
                                                                   opus_projection.h,
                                                                   opus_types.h, + licenses}
opus-1.6.1-binaries-x64-release.zip       opus-1.6.1/binaries/x64/Release/{opus.dll, opus.lib,
                                                                          opus.pdb, + licenses}
opus-1.6.1-binaries-x64-debug.zip         opus-1.6.1/binaries/x64/Debug/...
opus-1.6.1-binaries-win32-release.zip     opus-1.6.1/binaries/Win32/Release/...
opus-1.6.1-binaries-win32-debug.zip       opus-1.6.1/binaries/Win32/Debug/...
SHA256SUMS.txt

All zips share the opus-<ver>\ root, so they extract over each other into one tree. Zip filenames are lower-cased (...-win32-release.zip); the paths inside keep MSBuild's casing (binaries\Win32\Release\...), so the props can address them with $(Platform) and $(Configuration) directly.

Each archive ships Opus's COPYING (3-clause BSD), LICENSE_PLEASE_READ.txt (the patent grant notice) and AUTHORS next to its payload rather than at the package root — a root-level copy would be overwritten as the archives extract into the same folder.

Repository layout

.github/workflows/build-opus.yml   CI: build on a Windows runner, upload zip artifacts
build-opus.ps1                     the build + package script (shared by CI and Docker)
Dockerfile                         Windows-container toolchain image (for local/offline builds)
examples/freeswitch/w32/           reference MSBuild props for wiring up mod_opus
  ├─ opus.props                       downloads the zips, links opus.lib, copies opus.dll
  └─ opus-version.props               single place to set the Opus version
README.md

Building

Option A — GitHub Actions (recommended)

The Build Opus (Windows) workflow runs on a windows-2022 runner (which already has Visual Studio 2022, CMake and Git) and runs build-opus.ps1.

  • Manually: Actions tab → Build Opus (Windows)Run workflow, then enter the Opus tag (e.g. v1.6.1), configs (Release Debug) and platforms (x64 Win32).
  • By tag: push a tag like opus-v1.6.1. The workflow builds it and also attaches the zips to a GitHub Release — which is exactly where opus.props expects to find them.

A full x64 Win32 × Release Debug matrix takes only a few minutes; Opus is a small C library.

Option B — Local, via the Docker toolchain image

Useful for offline/air-gapped builds or reproducing CI locally. Requires Docker with Windows containers enabled.

# Build the toolchain image once (installs VS Build Tools, Git, CMake). This layer
# is large and slow; subsequent version builds reuse it.
docker build -t opus-packaging .

# Produce zips for an Opus tag (writes to .\artifacts on the host):
docker run --rm --cpus 8 --memory 8g `
  -e OPUS_VERSION=v1.6.1 `
  -v ${PWD}\artifacts:C:\artifacts `
  opus-packaging

cmd.exe: replace ${PWD} with %cd%.

Override any parameter with -e, e.g. x64 Release only:

docker run --rm --memory 8g -e OPUS_VERSION=v1.6.1 -e PLATFORMS=x64 -e CONFIGS=Release `
  -v ${PWD}\artifacts:C:\artifacts opus-packaging

The host must run a Windows base image of equal-or-older build for process isolation (the Dockerfile defaults to servercore:ltsc2025); otherwise pass --build-arg WINDOWS_BASE=...:ltsc2022 or run with --isolation=hyperv.

Option C — Local, native

If you already have Visual Studio 2017+ (C++ workload), CMake ≥ 3.16 and Git, just run the script directly — it locates VS via vswhere and picks the matching CMake generator itself:

$env:OPUS_VERSION = 'v1.6.1'
$env:CONFIGS      = 'Release Debug'
$env:PLATFORMS    = 'x64'
$env:OUT_DIR      = "$PWD\artifacts"
.\build-opus.ps1

Build parameters (env vars)

Var Default Notes
OPUS_VERSION v1.6.1 Any Opus git tag. A bare 1.6.1 is accepted too.
CONFIGS Release Debug Space-separated; set to Release to skip the Debug build.
PLATFORMS x64 Win32 Space-separated: x64, Win32, ARM64. These are MSBuild $(Platform) names.
PKG_PREFIX opus Zip/folder name prefix.
OUT_DIR C:\artifacts Where the zips are written (mount this in Docker).
OPUS_REPO https://gitlab.xiph.org/xiph/opus.git Override for a fork/mirror (e.g. the GitHub mirror).
OPUS_BUILD_ROOT C:\ob Scratch build dir (kept short to dodge MAX_PATH).
OPUS_CUSTOM_MODES OFF ON enables Opus custom modes and adds opus_custom.h to the headers zip.
CMAKE_GENERATOR (auto) Force a CMake generator. Auto-detected from the installed VS otherwise.

Consuming the zips in FreeSWITCH

Copy the two files from examples/freeswitch/w32/ into your FreeSWITCH build tree's w32\ directory, then in src\mod\codecs\mod_opus\mod_opus.2017.vcxproj:

  1. Import the props in each configuration's PropertySheets group (next to module_release.props / module_debug.props):

    <Import Project="..\..\..\..\w32\opus.props" />
  2. Drop the four in-tree Opus ProjectReference entries — opus.2017.vcxproj, opus.celt.2017.vcxproj, opus.silk_common.2017.vcxproj, opus.silk_float.2017.vcxproj. The props links the prebuilt opus.lib instead. Keep the FreeSwitchCore.2017.vcxproj reference.

  3. Drop the four ..\..\..\..\libs\opus-1.1\include entries from AdditionalIncludeDirectories; the props supplies the include paths.

Set the target version in opus-version.props, and if you publish the zips somewhere other than this repo's GitHub Releases, edit $(opusPkgBase) in opus.props. w32\download_opus.props and libs\win32\opus\ are then unused by mod_opus and can go.

The props handles the three consumer-side requirements automatically:

  1. Downloads and extracts the headers + the matching $(Platform)/$(Configuration) binaries into libs\opus-<ver>\.
  2. Adds both include and include\opus to the include path, so #include "opus.h" (what mod_opus uses) and #include <opus/opus.h> both resolve.
  3. Links opus.lib and copies opus.dll next to the FreeSWITCH binary.

How the build works

build-opus.ps1:

  1. git clone --depth 1 --branch <tag> the Opus source into a short scratch dir.
  2. Per platform × configuration, configures with CMake (Visual Studio generator, -A <Platform>) using OPUS_BUILD_SHARED_LIBRARY=ON — which is what defines DLL_EXPORT and so puts __declspec(dllexport) on Opus's OPUS_EXPORT public API — then cmake --build and cmake --install.
  3. Packages bin\opus.dll + lib\opus.lib from the install tree and opus.pdb from the build tree into the per-config binaries zip; packages include\opus\*.h into the headers zip; drops Opus's licences next to each payload; writes SHA256SUMS.txt.

Everything goes through cmake --install rather than being picked out of the build tree, so the layout is the same no matter which generator ran.

Notes & gotchas

  • Shared library, not static. FreeSWITCH currently links Opus statically from libs\win32\opus\; this package is a DLL, so opus.dll must ship alongside FreeSwitch.exe (the props copies it, exactly as the libnode and FFmpeg props do for theirs). To build static instead, flip OPUS_BUILD_SHARED_LIBRARY to OFF in build-opus.ps1 — but then drop the opusCopyTarget from the props, since there is no DLL to copy.
  • MSVC runtime. Built with the dynamic CRT (/MD, /MDd for Debug) — OPUS_STATIC_RUNTIME=OFF — which is what FreeSWITCH uses. A consumer built against a different CRT will crash on the first allocation crossing the DLL boundary.
  • Release PDBs. CMake's MSVC Release flags omit /Zi, so upstream ships no Release PDB. The script adds /Zi plus /DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO so release crash dumps stay symbolizable without changing the generated code.
  • opus_get_version_string(). Opus derives its own version from git describe, which resolves fine for the tagged shallow clone this script makes. The script passes -DOPUS_PACKAGE_VERSION=<ver> anyway to pin it for the cases where describe yields nothing — a source tarball, a mirror without tags, or a build tree detached from its .git — where the library would report libopus 0.
  • One benign build warning. cl : command line warning D9002: ignoring unknown option '-msse4.1' comes from Opus's own CMake handing MSVC a GCC-style flag. MSVC needs no switch to compile SSE4.1 intrinsics, so the vectorized paths are still built: the configure summary lists OPUS_X86_MAY_HAVE_SSE, SSE2, SSE4_1 and AVX2 as enabled, and Opus dispatches between them at run time.
  • DRED / OSCE / deep PLC are off. Those Opus 1.5+ features need the neural network model blobs (download_model.sh), which the CMake build does not fetch. Enabling them would mean vendoring or downloading the model data as well.
  • Custom modes are off (OPUS_CUSTOM_MODES=OFF), matching the in-tree FreeSWITCH build. mod_opus does not use them; set OPUS_CUSTOM_MODES=ON if some other consumer needs opus_custom.h.
  • 32-bit is supported here. Unlike libnode-packaging, Opus builds fine for Win32, so both platforms are produced by default.
  • No pkg-config or CMake package files. They bake in absolute install prefixes that this repo's zip layout invalidates, so OPUS_INSTALL_PKG_CONFIG_MODULE and OPUS_INSTALL_CMAKE_CONFIG_MODULE are both OFF.
  • Refreshing a dev checkout. The props re-copies opus.dll whenever it differs (SkipUnchangedFiles), but the download is skipped whenever libs\opus-<ver>\... already exists. After republishing a package for the same version, delete the extracted libs\opus-<ver>\ so it gets fetched again.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages