If you want to develop for OBS, please visit our Discord and get to know the devs or have questions answered!

Also, if there is something in this guide you want to change/improve on, it is recommended that you talk about it with the devs in Discord or IRC first.

Please note that any install directions/packages for Linux/FreeBSD distributions listed as Unofficial means that they are community provided, and any support for those packages should be directed at the appropriate distro/package maintainers.

OBS build dependencies

DependencyAvailable Pre-Built (macOS and Windows)
FFmpegYES
x264YES
cURLYES (required on Windows only)
mbedTLSYES
Chromium Embedded FrameworkYES
QtYES

We suggest having a current version of Git and CMake installed on the build system. macOS and Linux systems also require the Ninja build system to be installed, CCache can be installed to speed up consecutive builds as well and is supported by the build system.

The repository has build scripts for Windows, macOS and Linux available (written for Powershell and Bash respectively) that can set up build tools and dependencies for the developer as well as building and packaging OBS. Check out the OS-dependent chapters below for more detail on available functionality.

CMake

OBS uses CMake to create build environments for different platforms and IDEs. As a modular project, each module can introduce its own build options and requirements, which are gathered and managed by CMake when invoking it.

While these build options are detected and set automatically by CMake, they can also be changed after build configuration has finished or can be changed via overrides at configuration time.

This article explains some intricacies of OBS’ CMake build system structure and the available options to change its behavior.

OBS CMake Build System

OBS requires at least CMake v3.16 or newer due to many quality-of-life changes introduced in this version. On Windows and macOS the most current CMake version (as of writing v3.22) is preferred, even if the current feature level is capped to v3.21.

Due to OBS’ modular structure, some build configuration settings are available globally, while others are introduced by modules. They are listed here in order of appearance (as defined by each CMakeLists.txt file, which is processed procedurally by CMake).

Global Options

VariableDescriptionDefaultOS
CMAKE_BUILD_TYPESets the build configuration (available values are Debug, RelWithDebInfo, Release and MinSizeRel)RelWithDebInfoAll
CMAKE_INSTALL_PREFIXSets either an absolute installation path or path relative to the build directoryrundir inside build directory (install on macOS)All
CMAKE_PREFIX_PATHAdditional search path for dependencies, use semicolons to seperate multiple pathsNoneAll
CMAKE_OSX_ARCHITECTURESSpecify architecture(s) to build binaries for (available values are x86_64 and arm64)x86_64macOS
CMAKE_OSX_DEPLOYMENT_TARGETMinimum macOS versions to deploy binaries for10.13 for x86_64, 11.0 for arm64macOS
CEF_ROOT_DIRSpecify root directory of pre-built Chromium Embedded Framework (required for Browser source plugin)NoneAll
VLC_PATHSpecify directory of downloaded VLC source files (required for VST source plugin)NonemacOS and Windows

OBS Build Options

VariableDescriptionDefaultOS
ENABLE_UIEnable building with UI (main OBS application)ONAll
ENABLE_SCRIPTINGEnable scripting functionality (Lua and/or Python)ONAll
QT_VERSIONSpecify Qt build version to use (allowed: 5 | 6 | AUTO)AUTOAll
USE_LIBCXXUse libc++ instead of libstdc++ONmacOS
LINUX_PORTABLEUse a portable directory structure to run OBSOFFLinux
USE_XDGUtilize XDG base directory specificationONLinux
OBS_VERSION_OVERRIDESpecify OBS version for configured buildMost recent Git tagAll
OBS_BUILD_NUMBERContinuous build number for configured buildAutomatically incremented on local buildsAll
OBS_BUNDLE_CODESIGN_IDENTITYIdentity to use for code signing when building OBS application bundle-macOS
OBS_BUNDLE_CODESIGN_TEAMTeam to use for code signing when building OBS application bundleNonemacOS
OBS_CODESIGN_ENTITLEMENTSEntitlements to use for code signingShipped entitlements filemacOS
OBS_CODESIGN_LINKEREnable automatic linker codesigningON on macOS 11.0+, OFF otherwisemacOS
OBS_MULTIARCH_SUFFIXSpecific architecture suffix to use (available values are 32 or 64)NoneLinux

OBS Feature Options

VariableDescriptionDefaultOS
ENABLE_PLUGINSEnable building with pluginsONAll
ENABLE_SPARKLE_UPDATEREnable building with Sparkle updater frameworkOFFmacOS
ENABLE_WAYLANDEnable support for Wayland compositorONLinux
ENABLE_PIPEWIREEnable support for Pipewire graphics processing engineONLinux

OBS Module Options

VariableDescriptionDefaultOS
ENABLE_AJAEnable building with AJA NTV2 supportONAll
ENABLE_COREAUDIO_ENCODEREnable support for CoreAudio encoderONWindows (cannot be disabled on macOS)
ENABLE_DECKLINKEnable building with Decklink supportONAll
ENABLE_ALSAEnable building with Advanced Linux Sound Architecture (ALSA) supportONLinux
ENABLE_JACKEnable support for JACK audio serverOFFLinux
ENABLE_PULSEAUDIOEnable Pulse Aduio supportONLinux
ENABLE_V4L2Enable Video4Linux v2 supportONLinux
ENABLE_VIRTUALCAMEnable building with Virtual Camera modulesONWindows and macOS
VIRTUALCAM_GUIDSpecify global unique identifier (GUID) for Virtual Camera PluginNoneWindows
ENABLE_BROWSEREnable buidling Browser Source pluginONAll
ENABLE_BROWSER_LEGACYEnable building Browser Source plugin with legacy CEF version 3770OFFWindows
ENABLE_BROWSER_SHARED_TEXTUREEnable building Browser Source plugin with shared texture supportONWindows and macOS
ENABLE_BROWSER_QT_LOOPEnable building Browser source plugin with Qt message loopONmacOS
ENABLE_BROWSER_PANELSEnable building Browser source plugin with support for browser panelsONAll
ENABLE_FFMPEG_LOGGINGEnable more verbose logging for FFmpeg-based operationsOFFAll
ENABLE_SPEEXDSPEnable noise suppression using SpeexDSPONAll
ENABLE_RNNOISEEnable noise suppression using RNNoiseONAll
ENABLE_NVAFXEnable noise supporession using NVidia Audio Effects SDKONWindows
ENABLE_LIBFDKEnable building support for Fraunhofer AAC codecOFFAll
ENABLE_RTMPSEnable support for TLS-based RTMP connectionsAUTOAll
ENABLE_VSTEnable VST plugin supportONAll
ENABLE_VST_BUNDLED_HEADERSEnable building VST plugin with bundled headersONAll
ENABLE_OSSEnable building with Open Sound System supportONLinux
ENABLE_SERVICE_UPDATESEnable automatic streaming service updatesOFFAll
ENABLE_SNDIOEnable sndio framework supportOFFLinux
ENABLE_FREETYPEEnable support for FreeType 2 based text renderingONmacOS and Linux
ENABLE_VLCEnable support for VLC-based sourcesONAll
ENABLE_D3D12_HOOKEnable capture hook for Direct3D 12-based gamesOFFWindows
ENABLE_IVCAMEnable support for Realsense cameraOFFWindows

Windows-Specific Options

For improved support with legacy build setups, OBS will detect and “upgrade” the following older environment variables and cache variables:

VariableDescriptionExampleReplacement
DepsPathSet path to downloaded prebuilt dependenciesC:\Dev\dependencies2019\win64CMAKE_PREFIX_PATH
DepsPath32Set path to downloaded prebuilt 32-bit dependenciesC:\Dev\dependencies2019\win32CMAKE_PREFIX_PATH
DepsPath64Set path to downloaded prebuilt 64-bit dependenciesC:\Dev\dependencies2019\win64CMAKE_PREFIX_PATH
QTDIRSet path to Qt installationC:\Dev\Qt_5.15.2\msvc2019_64CMAKE_PREFIX_PATH
QTDIR32Set path to 32-bit Qt installationC:\Dev\Qt_5.15.2\msvc2019CMAKE_PREFIX_PATH
QTDIR64Set path to 64-bit Qt installationC:\Dev\Qt_5.15.2\msvc2019_64CMAKE_PREFIX_PATH
VlcPathSet path to VLC installationC:\Dev\vlc-3.0.0-gitVLC_Path

The following legacy option switches are supported for a grace period as well and are automatically upgraded as follows:

VariableUpgrade
BROWSER_LEGACYENABLE_BROWSER_LEGACY
BROWSER_PANEL_SUPPORT_ENABLEDENABLE_BROWSER_PANELS
BUILD_BROWSERENABLE_BROWSER
BUILD_CA_ENCODERENABLE_COREAUDIO_ENCODER
BUILD_VSTENABLE_VST
BROWSER_LEGACYENABLE_BROWSER_LEGACY
CHECK_FOR_SERVICE_UPDATESENABLE_SERVICE_UPDATES
DEBUG_FFMPEG_MUXENABLE_FFMPEG_MUX_DEBUG
DISABLE_IVCAMENABLE_IVCAM
DISABLE_PLUGINSENABLE_PLUGINS
DISABLE_PYTHONENABLE_SCRIPTING_PYTHON
DISABLE_LUAENABLE_SCRIPTING_LUA
DISABLE_SPEEXDSPENABLE_SPEEXDSP
DISABLE_UPDATE_MODULEENABLE_UPDATER
SHARED_TEXTURE_SUPPORT_ENABLEDENABLE_BROWSER_SHARED_TEXTURE
STATIC_MBEDTLSENABLE_STATIC_MBEDTLS
UNIX_STRUCTURELINUX_PORTABLE
USE_QT_LOOPENABLE_BROWSER_QT_LOOP
WITH_RTMPSENABLE_RTMPS

General CMake guidance

All these commands implicitly expect to be run from within the OBS source code directory checked out via git including all submodules (check the [Installing and Building]() page for more details):

Create Build Configuration

Just running cmake triggers an “in-source” build (meaning: build artifacts are placed with the source code directory structure). Due to OBS’ modular structure this build variant is not allowed, instead an “out-of-source” build needs to be configured.

To create a build configuration in a desired subdirectory run cmake -S . -B. This will configure OBS with most modules available to the host operating system enabled.

To change the CMake generator (and the build tool used to compile the project) pass a compatible generator name via the -G switch. Supported generators by CMake and OBS are:

  • Unix Makefiles
  • Ninja
  • Xcode
  • Visual Studio 17 2022
  • Visual Studio 16 2019

Other generators are supported by CMake but have neither been tested nor are officially supported by the OBS team.

Change Configuration Options

To change a configuration option, supported variables can be passed via the -D switch. E.g. to disable building with the browser plugin, pass -DENABLE_BROWSER=OFF. While CMake supports several values as binary switches, within OBS ON or OFF are used.

These changes are additive, as CMake stores these options as “cache variables” in a file called CMakeCache.txt in the specified build directory and reads from this file when cmake is run again. As such cache options can either be changed in this file directly, or overwritten by specifying new values for them via the -D switch (see above).

CMake GUIs

CMake build configurations can also be managed using graphical user interfaces: On Windows cmake-gui is installed with the CMake package available for the platform and allows selection of source and build directories (-S and -B switches respectively) as well as direct manipulation of all cache variables. Detailed instructions for this GUI are available in the [Installation and Building]() article.

On POSIX-based systems a ncurses-based user interface is available via the ccmake command which allows editing of cache variables. Note that due to CMake’s internal processes, a configuration step (via the c shortcut) needs to be repeated until no new cache variables are created by it. Only then will the generation step (g shortcut) be made available.

Apply Changes

Whether changes to CMake script files themselves or to cache variables, CMake needs to be run again to “pick up” on these changes and apply them (as build system files are generated according to these changes). When using the GUI a repeat run of configuration and generation steps should be enough to pick up those changes; when using the command line a repeat invocation of cmake -S . -B will do the same.

Modern CMake

OBS uses “Modern CMake” which differentiates from patterns and practices used by CMake before version 2.8/3 - for the full details please refer to An Introduction To Modern CMake.

Here are some general rules of thumb (lifted from the article mentioned above):

CMake Antipatterns

  • Do not use global functions: This includes link_directories, include_libraries, and similar.
  • Don’t add unneeded PUBLIC requirements: You should avoid forcing something on users that is not required (-Wall). Make these PRIVATE instead.
  • Don’t GLOB files: Make or another tool will not know if you add files without rerunning CMake. Note that CMake 3.12 adds a CONFIGURE_DEPENDS flag that makes this far better if you need to use it.
  • Do not link to built files directly: Always link to targets if available.
  • Never skip PUBLIC/PRIVATE when linking: This causes all future linking to be keyword-less.

CMake Patterns

  • Treat CMake as code: It is code. It should be as clean and readable as all other code.
  • Think in targets: Your targets should represent concepts. Make an (IMPORTED) INTERFACE target for anything that should stay together and link to that.
  • Export your interface: You should be able to run from build or install.
  • Write a Config.cmake file: This is what a library author should do to support clients.
  • Make ALIAS targets to keep usage consistent: Using add_subdirectory and find_package should provide the same targets and namespaces.
  • Combine common functionality into clearly documented functions or macros: Functions are better usually.
  • Use lowercase function names: CMake functions and macros can be called lower or upper case. Always use lower case. Upper case is for variables.
  • Use cmake_policy and/or range of versions: Policies change for a reason. Only piecemeal set OLD policies if you have to.

Examples

  • Using (internal) finder variables to add libraries and their include directories:

    1. LEGACY:
    2. ---------------
    3. find_package(MyLibrary)
    4. link_directores(${MY_LIBRARY_INCLUDE_DIRS})
    5. include_libraries(${MY_LIBRARY_LIB})
    6. MODERN:
    7. ---------------
    8. find_package(MyLibrary)
    9. target_link_libraries(my_target PRIVATE My_Library::My_Library)

    NOTE: If the package does not create an imported library target (My_Library::My_Library), an issue should be filed with the respective library maintainer(s) to drop the outdated FindXYZ.cmake pattern and update to CMake’s export function to create a CMake package. In the interim the finder module can be patched to create namespaced imported targets (see some examples in OBS’ CMake/Modules directory.

  • Gathering source files in variables and adding them at the bottom of the script:

    1. LEGACY:
    2. ---------------
    3. set(mytarget_SOURCES
    4. my_source.c)
    5. set(mytarget_HEADERS
    6. include/my_headers.h)
    7. add_library(my_target SHARED ${mytarget_SOURCES} ${mytarget_HEADERS)
    8. MODERN:
    9. ---------------
    10. add_library(my_target SHARED)
    11. target_sources(my_target
    12. include/my_headers.h)
  • Polluting the build environment with local compilation requirements

    1. LEGACY:
    2. ---------------
    3. set(CMAKE_CXX_STANDARD 17)
    4. set(CMAKE_CXX_STANDARD_REQUIRED ON)
    5. set(CMAKE_CXX_EXTENSIONS OFF)
    6. add_compile_options(-Wextra -Wvla -Wno-unused-function -Wno-missing-field-initializers -fno-strict-aliasing)
    7. add_link_options(/INCREMENTAL)
    8. MODERN:
    9. ---------------
    10. target_compile_features(my_target PRIVATE cxx_std_17)
    11. target_compile_options(my_target PRIVATE -Wextra PUBLIC -fno-strict-aliasing)
    12. target_link_options(my_target PRIVATE LINKER:-z,defs)

    NOTE: The correct use of PRIVATE and PUBLIC is important here: PRIVATE target properties only apply to the target itself, while PUBLIC options are also inherited by targets linking to this target. Also note the LINKER: prefix for the link options - this allows CMake to use the compiler specific linker flags (e.g -Xlinker -z -Xlinker defs for Clang and -Wl,-z,defs for GNU GCC).

Think In Targets

This cannot be stressed enough: In Modern CMake everything revolves around targets, which allows CMake to resolve dependencies and relationships using target properties and the information contained within. E.g. when linking target_a with target_b (via target_link_libraries()) CMake will look up the INTERFACE_INCLUDE_DIRECTORIES property on target_b to yield the directory containing library headers, as well as INTERFACE_LINK_LIBRARIES which will contain the actual library files in the file system. Required compile options and defines are also read from INTERFACE_COMPILE_OPTIONS and INTERFACE_COMPILE_DEFINITIONS respectively and added to target_a‘s compile options automatically.

Using namespaces (My_Library::My_Library) when specifying targets for linking has the added benefit of ensuring a target reference (instead of a file reference), as colons are invalid for file names in many file systems.