Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/scripts/.Aptfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ package 'git'
package 'jq'
package 'ninja-build', bin: 'ninja'
package 'pkg-config'

# FFmpeg dev libraries: the MoQ source decodes video with libav*, found via
# pkg-config on Linux (macOS/Windows use the obs-deps bundle instead).
package 'libavcodec-dev'
package 'libavutil-dev'
package 'libswscale-dev'
package 'libswresample-dev'
4 changes: 3 additions & 1 deletion .github/scripts/build-macos
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ build() {
}
}

# arm64-only: the plugin links a published libmoq release, which ships
# per-architecture (no universal archive), so a universal plugin can't link
# the x86_64 slice. Build arm64 only to match the fetched libmoq.
local -a build_args=(
ONLY_ACTIVE_ARCH=NO
-arch arm64
-arch x86_64
-project ${product_name}.xcodeproj
-target ${product_name}
-destination "generic/platform=macOS,name=Any Mac"
Expand Down
21 changes: 15 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,21 @@ add_library(obs-moq MODULE)

if(${BUILD_PLUGIN})
find_package(libobs REQUIRED)
# FFmpeg dependency
include(FindPkgConfig)
pkg_check_modules(FFMPEG REQUIRED libavcodec libavutil libswscale libswresample)
target_include_directories(obs-moq PRIVATE ${FFMPEG_INCLUDE_DIRS})
target_link_directories(obs-moq PRIVATE ${FFMPEG_LIBRARY_DIRS})
target_link_libraries(obs-moq PRIVATE ${FFMPEG_LIBRARIES})
# FFmpeg dependency (used by the MoQ source to decode subscribed video). On
# macOS and Windows, link the ffmpeg the obs-deps bundle ships -- the same one
# OBS itself uses at runtime -- via the vendored FindFFmpeg finder (obs-deps
# ship ffmpeg with no pkg-config .pc files, so it searches the prefix). On
# Linux there's no obs-deps; pkg-config finds the system ffmpeg.
if(WIN32 OR APPLE)
find_package(FFmpeg REQUIRED avcodec avutil swscale swresample)
target_link_libraries(obs-moq PRIVATE FFmpeg::avcodec FFmpeg::avutil FFmpeg::swscale FFmpeg::swresample)
else()
include(FindPkgConfig)
pkg_check_modules(FFMPEG REQUIRED libavcodec libavutil libswscale libswresample)
target_include_directories(obs-moq PRIVATE ${FFMPEG_INCLUDE_DIRS})
target_link_directories(obs-moq PRIVATE ${FFMPEG_LIBRARY_DIRS})
target_link_libraries(obs-moq PRIVATE ${FFMPEG_LIBRARIES})
endif()
else()
find_package(FFmpeg REQUIRED avcodec avutil swscale swresample)
target_link_libraries(obs-moq PRIVATE FFmpeg::avcodec FFmpeg::avutil FFmpeg::swscale FFmpeg::swresample)
Expand Down
163 changes: 163 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#!/usr/bin/env bash
set -euo pipefail

# Build and package the obs-moq plugin for release.
# Usage: ./build.sh [--target TARGET] [--version VERSION] [--output DIR]
#
# The required toolchain must already be on PATH; this script only drives
# CMake. Per platform:
# Linux - run inside `nix develop` (provides cmake/ninja/obs-studio/qt6/ffmpeg)
# macOS - full Xcode, run OUTSIDE nix (libobs/Qt6/ffmpeg all come from the
# obs-deps bundle downloaded by buildspec.json at configure time)
# Windows - Visual Studio 2022; run from Git Bash with cmake on PATH
# (libobs/Qt6 downloaded by buildspec.json)
#
# Produces $OUTPUT_DIR/obs-moq-$VERSION-$TARGET.{tar.gz,zip}. The archive is
# unsigned; macOS Gatekeeper / Windows SmartScreen will warn on first load.

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

TARGET=""
VERSION=""
OUTPUT_DIR="dist"
MOQ_RELEASE=""

while [[ $# -gt 0 ]]; do
case $1 in
--target)
TARGET="$2"
shift 2
;;
--version)
VERSION="$2"
shift 2
;;
--output)
OUTPUT_DIR="$2"
shift 2
;;
--libmoq-release)
# Link a published libmoq release of this version instead of
# building rs/libmoq from source. CMake fetches the matching
# moq-<version>-<target> archive from the GitHub release and the
# plugin is versioned to match. Used by CI on a libmoq-v* tag.
MOQ_RELEASE="$2"
shift 2
Comment on lines +25 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Flag options that are missing a required value.

For --target/--version/--output/--libmoq-release, the parser reads $2 without checking it exists. With set -u, this exits abruptly with an unhelpful shell error.

Suggested fix
+require_value() {
+  if [[ $# -lt 2 || "$2" == --* ]]; then
+    echo "Missing value for $1" >&2
+    exit 1
+  fi
+}
+
 while [[ $# -gt 0 ]]; do
 	case $1 in
 	--target)
+		require_value "$@"
 		TARGET="$2"
 		shift 2
 		;;
 	--version)
+		require_value "$@"
 		VERSION="$2"
 		shift 2
 		;;
 	--output)
+		require_value "$@"
 		OUTPUT_DIR="$2"
 		shift 2
 		;;
 	--libmoq-release)
+		require_value "$@"
 		# Link a published libmoq release of this version instead of
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.sh` around lines 25 - 45, The flag option parser for --target,
--version, --output, and --libmoq-release does not validate that their required
argument values exist before accessing $2, which causes unhelpful shell errors
when set -u is enabled. Add validation before each variable assignment (TARGET,
VERSION, OUTPUT_DIR, MOQ_RELEASE) to check that $2 is not empty and is not
another flag, and provide clear error messages indicating which flag is missing
its required value.

;;
-h | --help)
echo "Usage: $0 [--target TARGET] [--version VERSION] [--output DIR] [--libmoq-release VERSION]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done

# In libmoq-release mode the plugin version tracks the libmoq version.
if [[ -n "$MOQ_RELEASE" ]]; then
VERSION="$MOQ_RELEASE"
fi

if [[ -z "$TARGET" ]]; then
TARGET=$(cc -dumpmachine 2>/dev/null || echo unknown)
echo "Detected target: $TARGET"
fi

# Default the version from buildspec.json's top-level "version" (the nested
# dependency entries also have "version" keys, hence the leading-indent anchor).
if [[ -z "$VERSION" ]]; then
VERSION=$(grep -E '^[[:space:]]{4}"version"' "$SCRIPT_DIR/buildspec.json" | head -1 | sed 's/.*: *"\([^"]*\)".*/\1/')
echo "Detected version: $VERSION"
fi

# Map the target triple to a CMake preset and build tree.
case "$TARGET" in
*-linux-*)
PRESET="ubuntu-x86_64"
BUILD_DIR="$SCRIPT_DIR/build_x86_64"
KIND="unix"
;;
*-apple-darwin)
PRESET="macos"
BUILD_DIR="$SCRIPT_DIR/build_macos"
KIND="macos"
;;
*-windows-*)
PRESET="windows-x64"
BUILD_DIR="$SCRIPT_DIR/build_x64"
KIND="windows"
;;
*)
echo "Unsupported target: $TARGET" >&2
exit 1
;;
Comment on lines +76 to +95

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

macOS auto-detection pattern is too strict and can reject valid triples.

cc -dumpmachine on macOS commonly includes a Darwin version suffix (for example, arm64-apple-darwin23.x.y), which does not match *-apple-darwin and falls into “Unsupported target”.

Suggested fix
-*-apple-darwin)
+*-apple-darwin*)
  PRESET="macos"
  BUILD_DIR="$SCRIPT_DIR/build_macos"
  KIND="macos"
  ;;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "$TARGET" in
*-linux-*)
PRESET="ubuntu-x86_64"
BUILD_DIR="$SCRIPT_DIR/build_x86_64"
KIND="unix"
;;
*-apple-darwin)
PRESET="macos"
BUILD_DIR="$SCRIPT_DIR/build_macos"
KIND="macos"
;;
*-windows-*)
PRESET="windows-x64"
BUILD_DIR="$SCRIPT_DIR/build_x64"
KIND="windows"
;;
*)
echo "Unsupported target: $TARGET" >&2
exit 1
;;
case "$TARGET" in
*-linux-*)
PRESET="ubuntu-x86_64"
BUILD_DIR="$SCRIPT_DIR/build_x86_64"
KIND="unix"
;;
*-apple-darwin*)
PRESET="macos"
BUILD_DIR="$SCRIPT_DIR/build_macos"
KIND="macos"
;;
*-windows-*)
PRESET="windows-x64"
BUILD_DIR="$SCRIPT_DIR/build_x64"
KIND="windows"
;;
*)
echo "Unsupported target: $TARGET" >&2
exit 1
;;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.sh` around lines 76 - 95, The macOS pattern matching in the case
statement checking against TARGET is too restrictive. The pattern
`*-apple-darwin` does not match triples with Darwin version suffixes like
`arm64-apple-darwin23.x.y`, causing valid macOS targets to fall through to the
unsupported case. Update the pattern for the macOS branch to use
`*-apple-darwin*` to match triples with optional Darwin version suffixes
following the word "darwin".

esac

# Resolve the output dir to an absolute path before we cd into the plugin
# directory (cmake --preset reads CMakePresets.json from the current dir).
mkdir -p "$OUTPUT_DIR"
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
cd "$SCRIPT_DIR"

echo "Building obs-moq $VERSION for $TARGET (preset: $PRESET)..."
CONFIGURE_ARGS=()
# Stamp the plugin's compiled-in version (project version, macOS Info.plist,
# Windows resource) to match what we're building, not buildspec.json's 0.0.1.
if [[ -n "$VERSION" ]]; then
CONFIGURE_ARGS+=("-DPLUGIN_VERSION_OVERRIDE=$VERSION")
fi
if [[ -n "$MOQ_RELEASE" ]]; then
# Empty MOQ_LOCAL forces CMake's release-download branch; MOQ_VERSION and
# MOQ_TARGET steer it at this target's archive (the presets hard-code an
# x86_64/stale default). MOQ_ARCHIVE is correct per preset already.
echo "Linking libmoq release v$MOQ_RELEASE ($TARGET)"
CONFIGURE_ARGS+=(-DMOQ_LOCAL= "-DMOQ_VERSION=$MOQ_RELEASE" "-DMOQ_TARGET=$TARGET")
fi
cmake --preset "$PRESET" ${CONFIGURE_ARGS[@]+"${CONFIGURE_ARGS[@]}"}
cmake --build --preset "$PRESET"

NAME="obs-moq-${VERSION}-${TARGET}"
STAGE="$OUTPUT_DIR/$NAME"
rm -rf "$STAGE"
mkdir -p "$OUTPUT_DIR"

if [[ "$KIND" == "macos" ]]; then
# Self-contained loadable bundle; drop into the OBS plugins directory.
PLUGIN=$(find "$BUILD_DIR" -name 'obs-moq.plugin' -maxdepth 4 -print -quit)
[[ -n "$PLUGIN" ]] || {
echo "obs-moq.plugin not found under $BUILD_DIR" >&2
exit 1
}
mkdir -p "$STAGE"
cp -R "$PLUGIN" "$STAGE/"
else
# OBS portable-plugin layout: extract into your OBS plugins directory.
LIB=$(find "$BUILD_DIR" \( -name 'obs-moq.so' -o -name 'obs-moq.dll' \) -print -quit)
[[ -n "$LIB" ]] || {
echo "obs-moq.{so,dll} not found under $BUILD_DIR" >&2
exit 1
}
mkdir -p "$STAGE/obs-moq/bin/64bit"
cp "$LIB" "$STAGE/obs-moq/bin/64bit/"
cp -R "$SCRIPT_DIR/data" "$STAGE/obs-moq/"
fi

cp "$SCRIPT_DIR/LICENSE" "$STAGE/"
cp "$SCRIPT_DIR/README.md" "$STAGE/"

# Archive with CMake's tar so we don't depend on zip/gtar being present
# (notably on the Windows runner). tar.gz on unix, zip on macOS/Windows.
(
cd "$OUTPUT_DIR"
if [[ "$KIND" == "unix" ]]; then
ARCHIVE="$NAME.tar.gz"
cmake -E tar czf "$ARCHIVE" "$NAME"
else
ARCHIVE="$NAME.zip"
cmake -E tar cf "$ARCHIVE" --format=zip "$NAME"
fi
rm -rf "$NAME"
echo "Created: $OUTPUT_DIR/$ARCHIVE"
)
Loading
Loading