obs-windows-building

📁 meriley/claude-code-skills 📅 5 days ago
1
总安装量
1
周安装量
#43414
全站排名
安装命令
npx skills add https://github.com/meriley/claude-code-skills --skill obs-windows-building

Agent 安装分布

amp 1
opencode 1
kimi-cli 1
codex 1
github-copilot 1
claude-code 1

Skill 文档

OBS Windows Building

Purpose

Build OBS Studio plugins for Windows using MSVC (Visual Studio) or MinGW. Covers symbol exports, Windows-specific linking, platform source files, and DLL verification.

When NOT to Use

  • Cross-compiling from Linux → Use obs-cross-compiling
  • Qt/C++ frontend development → Use obs-cpp-qt-patterns
  • Audio plugin implementation → Use obs-audio-plugin-writing
  • Code review → Use obs-plugin-reviewing

Quick Start: Windows Build in 4 Steps

Step 1: Install Prerequisites

Visual Studio 2022:

  • Workload: “Desktop development with C++”
  • Individual components: CMake, Windows SDK

Or MinGW (via MSYS2):

pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake

Step 2: Create Windows CMake Preset

{
  "name": "windows-x64",
  "displayName": "Windows x64",
  "description": "Build for Windows x64 with Visual Studio",
  "binaryDir": "${sourceDir}/build_x64",
  "generator": "Visual Studio 17 2022",
  "architecture": "x64",
  "cacheVariables": {
    "OBS_SOURCE_DIR": "${sourceDir}/.deps/windows-x64/obs-studio-32.0.4"
  }
}

Step 3: Create .def Export File

Create src/plugin.def:

LIBRARY my-plugin
EXPORTS
    obs_module_load
    obs_module_unload
    obs_module_post_load
    obs_module_ver
    obs_module_set_pointer
    obs_current_module
    obs_module_description
    obs_module_set_locale
    obs_module_free_locale
    obs_module_get_string
    obs_module_text

Step 4: Configure CMakeLists.txt

if(WIN32)
    # Windows system libraries
    target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 comctl32)

    # Export module functions via .def file
    if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
        # MinGW
        set_target_properties(${PROJECT_NAME} PROPERTIES
            LINK_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/src/plugin.def -Wl,--unresolved-symbols=ignore-all"
        )
    else()
        # MSVC
        set_target_properties(${PROJECT_NAME} PROPERTIES
            LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/plugin.def"
        )
    endif()
endif()

MSVC vs MinGW Comparison

Aspect MSVC MinGW
IDE Visual Studio VS Code, CLion
Debugging Full VS debugger GDB
Build speed Slower Faster
ABI Native Windows GCC-based
Qt compat Requires MSVC Qt Works with MinGW Qt
CI/CD Windows runner Linux cross-compile

Recommendation: Use MSVC for native Windows development, MinGW for CI cross-compilation.

Symbol Export with .def Files

Why .def Files?

OBS loads plugins at runtime and looks up functions by name. Without explicit exports:

  • MSVC may not export functions without __declspec(dllexport)
  • MinGW may export by ordinal only (numbers, not names)

.def File Format

; Comments start with semicolon
LIBRARY my-plugin        ; DLL name
EXPORTS
    obs_module_load      ; Function to export
    obs_module_unload
    ; Add all OBS_DECLARE_MODULE() and OBS_MODULE_USE_DEFAULT_LOCALE() functions

MSVC Linker Flag

set_target_properties(${PROJECT_NAME} PROPERTIES
    LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/plugin.def"
)

MinGW Linker Flag

set_target_properties(${PROJECT_NAME} PROPERTIES
    LINK_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/src/plugin.def -Wl,--unresolved-symbols=ignore-all"
)

Windows System Libraries

Common Libraries

Library Purpose Header
ws2_32 Windows Sockets 2 (networking) <winsock2.h>
comctl32 Common controls (UI widgets) <commctrl.h>
user32 Windows API (windows, messages) <windows.h>
kernel32 Core Windows API <windows.h>
ole32 COM support <objbase.h>
uuid GUID/UUID support <guiddef.h>

CMake Linking

if(WIN32)
    target_link_libraries(${PROJECT_NAME} PRIVATE
        ws2_32      # Sockets
        comctl32    # UI controls
    )
endif()

Include Order (CRITICAL)

/* WRONG - will cause compile errors */
#include <windows.h>
#include <winsock2.h>

/* CORRECT - winsock2.h must come first */
#include <winsock2.h>
#include <windows.h>

Platform-Specific Source Files

Directory Structure

src/
├── plugin-main.c           # Cross-platform
├── my-source.c             # Cross-platform
└── platform/
    ├── socket-posix.c      # Linux/macOS
    └── socket-win32.c      # Windows

CMakeLists.txt Pattern

# Common sources
target_sources(${PROJECT_NAME} PRIVATE
    src/plugin-main.c
    src/my-source.c
)

# Platform-specific sources
if(WIN32)
    target_sources(${PROJECT_NAME} PRIVATE
        src/platform/socket-win32.c
    )
else()
    target_sources(${PROJECT_NAME} PRIVATE
        src/platform/socket-posix.c
    )
endif()

Platform Header Pattern

/* platform.h - Platform abstraction */
#pragma once

#ifdef _WIN32
    #include "platform/socket-win32.h"
#else
    #include "platform/socket-posix.h"
#endif

/* Common interface */
int platform_socket_init(void);
void platform_socket_cleanup(void);
int platform_socket_send(const char *host, int port, const void *data, size_t len);

Windows-Specific Code Patterns

Winsock Initialization

/* socket-win32.c */
#include <winsock2.h>
#include <ws2tcpip.h>

static bool winsock_initialized = false;

int platform_socket_init(void)
{
    WSADATA wsa_data;
    int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
    if (result != 0) {
        return -1;
    }
    winsock_initialized = true;
    return 0;
}

void platform_socket_cleanup(void)
{
    if (winsock_initialized) {
        WSACleanup();
        winsock_initialized = false;
    }
}

Windows API Loader Pattern

For optional Windows APIs (not always available):

/* api-loader.c */
#include <windows.h>

typedef BOOL (WINAPI *SetProcessDpiAwarenessContext_t)(DPI_AWARENESS_CONTEXT);

static SetProcessDpiAwarenessContext_t pSetProcessDpiAwarenessContext = NULL;

void load_optional_apis(void)
{
    HMODULE user32 = GetModuleHandleW(L"user32.dll");
    if (user32) {
        pSetProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext_t)
            GetProcAddress(user32, "SetProcessDpiAwarenessContext");
    }
}

void set_dpi_awareness(void)
{
    if (pSetProcessDpiAwarenessContext) {
        pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
    }
}

OBS Plugin Installation Paths

User Installation (Recommended)

%APPDATA%\obs-studio\plugins\my-plugin\
├── bin\
│   └── 64bit\
│       └── my-plugin.dll
└── data\
    └── locale\
        └── en-US.ini

System Installation

C:\ProgramData\obs-studio\plugins\my-plugin\
├── bin\
│   └── 64bit\
│       └── my-plugin.dll
└── data\
    └── locale\
        └── en-US.ini

CMake Install Target

if(WIN32)
    set(OBS_PLUGIN_DIR "$ENV{APPDATA}/obs-studio/plugins/${PROJECT_NAME}")
endif()

install(TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION ${OBS_PLUGIN_DIR}/bin/64bit
)

install(DIRECTORY data/locale
    DESTINATION ${OBS_PLUGIN_DIR}/data
)

DLL Verification

Check File Type

:: PowerShell
Get-Item my-plugin.dll | Select-Object Name, Length

Check Exports with dumpbin (MSVC)

dumpbin /exports my-plugin.dll

Expected output:

    ordinal hint RVA      name
          1    0 00001000 obs_current_module
          2    1 00001010 obs_module_description
          3    2 00001020 obs_module_load
          ...

Check Exports with objdump (MinGW)

x86_64-w64-mingw32-objdump -p my-plugin.dll | grep -A 50 "Export Table"

FORBIDDEN Patterns

Pattern Problem Solution
Missing .def file Functions not exported by name Create plugin.def
Wrong include order winsock2 errors Include winsock2.h before windows.h
Missing WSAStartup Socket functions fail Call platform_socket_init()
Hardcoded paths Breaks on other machines Use %APPDATA% or relative paths
ANSI APIs Unicode issues Use wide (W) APIs or UTF-8
Missing /DEF linker flag No exports in DLL Add LINK_FLAGS in CMake

Troubleshooting

Plugin Not Visible in OBS

Check:

  1. DLL is in bin/64bit/ subdirectory
  2. Path is correct: %APPDATA%\obs-studio\plugins\{name}\bin\64bit\
  3. DLL exports are present: dumpbin /exports my-plugin.dll

“Entry Point Not Found” Error

Cause: Missing obs_module_load export

Fix: Ensure .def file includes obs_module_load and linker flag is set.

Winsock Errors

Symptom: Socket functions return -1 or WSANOTINITIALISED

Fix: Call WSAStartup() before any socket operations.

Unicode/ANSI Mismatch

Symptom: String corruption, “???” characters

Fix:

/* Use wide APIs or define UNICODE */
#define UNICODE
#define _UNICODE
#include <windows.h>

Build Commands

Visual Studio

:: Configure
cmake --preset windows-x64

:: Build
cmake --build --preset windows-x64 --config RelWithDebInfo

:: Install
cmake --install build_x64 --config RelWithDebInfo

MinGW (MSYS2)

# Configure
cmake -G "Ninja" -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo

# Build
cmake --build build

# Install
cmake --install build

External Documentation

Context7

mcp__context7__query-docs
libraryId: "/obsproject/obs-studio"
query: "Windows plugin build Visual Studio MSVC"

Official References

Related Skills

  • obs-cross-compiling – Cross-compile from Linux to Windows
  • obs-cpp-qt-patterns – Qt frontend integration
  • obs-plugin-developing – Plugin architecture overview
  • obs-audio-plugin-writing – Audio plugin implementation

Related Agent

Use obs-plugin-expert for coordinated guidance across all OBS plugin skills.