CI: Delete legacy build and formatting check scripts

This commit is contained in:
PatTheMav 2023-05-10 14:44:14 +02:00
parent 0838b74060
commit 0993147954
No known key found for this signature in database
22 changed files with 0 additions and 2013 deletions

View file

@ -1,105 +0,0 @@
#!/bin/bash
##############################################################################
# Linux full build script
##############################################################################
#
# This script contains all steps necessary to:
#
# * Build OBS with all default plugins and dependencies
# * Package a Linux deb package
#
# Parameters:
# -h, --help : Print usage help
# -q, --quiet : Suppress most build process output
# -v, --verbose : Enable more verbose build process output
# -d, --skip-dependency-checks : Skip dependency checks (default: off)
# -p, --portable : Create portable build (default: off)
# -pkg, --package : Create distributable disk image
# (default: off)
# --build-dir : Specify alternative build directory
# (default: build)"
#
##############################################################################
# Halt on errors
set -eE
## SET UP ENVIRONMENT ##
_RUN_OBS_BUILD_SCRIPT=TRUE
PRODUCT_NAME="OBS-Studio"
CHECKOUT_DIR="$(git rev-parse --show-toplevel)"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_linux.sh"
## DEPENDENCY INSTALLATION
source "${CHECKOUT_DIR}/CI/linux/01_install_dependencies.sh"
## BUILD OBS ##
source "${CHECKOUT_DIR}/CI/linux/02_build_obs.sh"
## PACKAGE OBS AND NOTARIZE ##
source "${CHECKOUT_DIR}/CI/linux/03_package_obs.sh"
## MAIN SCRIPT FUNCTIONS ##
print_usage() {
echo "build-linux.sh - Build script for OBS-Studio\n"
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-d, --skip-dependency-checks : Skip dependency checks (default: off)\n" \
"-p, --portable : Create portable build (default: off)\n" \
"-pkg, --package : Create distributable disk image (default: off)\n" \
"--disable-pipewire : Disable building with PipeWire support (default: off)\n" \
"--build-dir : Specify alternative build directory (default: build)\n"
}
obs-build-main() {
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-d | --skip-dependency-checks ) SKIP_DEP_CHECKS=TRUE; shift ;;
-p | --portable ) PORTABLE=TRUE; shift ;;
-pkg | --package ) PACKAGE=TRUE; shift ;;
--disable-pipewire ) DISABLE_PIPEWIRE=TRUE; shift ;;
--build-dir ) BUILD_DIR="${2}"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
ensure_dir "${CHECKOUT_DIR}"
step "Fetching OBS tags..."
git fetch origin --tags
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
GIT_HASH=$(git rev-parse --short HEAD)
GIT_TAG=$(git describe --tags --abbrev=0)
if [ "${BUILD_FOR_DISTRIBUTION}" ]; then
VERSION_STRING="${GIT_TAG}"
else
VERSION_STRING="${GIT_TAG}-${GIT_HASH}"
fi
FILE_NAME="obs-studio-${VERSION_STRING}-Linux.deb"
if [ -z "${SKIP_DEP_CHECKS}" ]; then
install_dependencies
fi
build_obs
if [ "${PACKAGE}" ]; then
package_obs
fi
cleanup
}
obs-build-main $*

View file

@ -1,143 +0,0 @@
#!/bin/bash
##############################################################################
# macOS build script
##############################################################################
#
# This script contains all steps necessary to:
#
# * Build OBS with all default plugins and dependencies
# * Create a macOS application bundle
# * Codesign the macOS application bundle
# * Package a macOS installation image
# * Notarize macOS application bundle and/or installation image
#
# Parameters:
# -h, --help : Print usage help
# -q, --quiet : Suppress most build process output
# -v, --verbose : Enable more verbose build process output
# -d, --skip-dependency-checks : Skip dependency checks (default: off)
# -b, --bundle : Create relocatable application bundle
# (default: off)
# -p, --package : Create distributable disk image
# (default: off)
# -c, --codesign : Codesign OBS and all libraries
# (default: ad-hoc only)
# -n, --notarize : Notarize OBS (default: off)
#
##############################################################################
# Halt on errors
set -eE
## SET UP ENVIRONMENT ##
_RUN_OBS_BUILD_SCRIPT=TRUE
PRODUCT_NAME="OBS-Studio"
CHECKOUT_DIR="$(/usr/bin/git rev-parse --show-toplevel)"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_macos.sh"
## INSTALL DEPENDENCIES ##
source "${CHECKOUT_DIR}/CI/macos/01_install_dependencies.sh"
## BUILD OBS ##
source "${CHECKOUT_DIR}/CI/macos/02_build_obs.sh"
## PACKAGE OBS AND NOTARIZE ##
source "${CHECKOUT_DIR}/CI/macos/03_package_obs.sh"
## MAIN SCRIPT FUNCTIONS ##
print_usage() {
echo "build-macos.sh - Build script for OBS-Studio"
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-a, --architecture : Specify build architecture (default: x86_64, alternative: arm64)\n" \
"-d, --skip-dependency-checks : Skip dependency checks (default: off)\n" \
"-b, --bundle : Create relocatable application bundle (default: off)\n" \
"-p, --package : Create distributable disk image (default: off)\n" \
"-c, --codesign : Codesign OBS and all libraries (default: ad-hoc only)\n" \
"-n, --notarize : Notarize OBS (default: off)\n"
}
print_deprecation() {
echo -e "DEPRECATION ERROR:\n" \
"The '${1}' switch has been deprecated!\n"
if [ "${1}" = "-s" ]; then
echo -e "The macOS build script system has changed:\n" \
" - To configure and build OBS, run the script 'CI/macos/02_build_obs.sh'\n" \
" - To bundle OBS into a relocatable application bundle, run the script 'CI/macos/02_build_obs.sh --bundle\n" \
" - To package OBS, run the script 'CI/macos/03_package_obs.sh'\n" \
" - To notarize OBS, run the script 'CI/macos/03_package_obs.sh --notarize'\n"
fi
}
obs-build-main() {
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-a | --architecture ) ARCH="${2}"; shift 2 ;;
-d | --skip-dependency-checks ) SKIP_DEP_CHECKS=TRUE; shift ;;
-p | --package ) PACKAGE=TRUE; shift ;;
-c | --codesign ) CODESIGN=TRUE; shift ;;
-n | --notarize ) NOTARIZE=TRUE; PACKAGE=TRUE CODESIGN=TRUE; shift ;;
-b | --bundle ) BUNDLE=TRUE; shift ;;
-s ) print_deprecation ${1}; exit 1 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
ensure_dir "${CHECKOUT_DIR}"
check_archs
check_macos_version
step "Fetching OBS tags..."
/usr/bin/git fetch origin --tags
GIT_BRANCH=$(/usr/bin/git rev-parse --abbrev-ref HEAD)
GIT_HASH=$(/usr/bin/git rev-parse --short HEAD)
GIT_TAG=$(/usr/bin/git describe --tags --abbrev=0)
if [ "${BUILD_FOR_DISTRIBUTION}" ]; then
VERSION_STRING="${GIT_TAG}"
else
VERSION_STRING="${GIT_TAG}-${GIT_HASH}"
fi
if [ "${ARCH}" = "arm64" ]; then
FILE_NAME="obs-studio-${VERSION_STRING}-macOS-Apple.dmg"
elif [ "${ARCH}" = "universal" ]; then
FILE_NAME="obs-studio-${VERSION_STRING}-macOS.dmg"
else
FILE_NAME="obs-studio-${VERSION_STRING}-macOS-Intel.dmg"
fi
if [ -z "${SKIP_DEP_CHECKS}" ]; then
install_dependencies
fi
build_obs
if [ "${BUNDLE}" ]; then
bundle_obs
fi
if [ "${PACKAGE}" ]; then
package_obs
fi
if [ "${NOTARIZE}" ]; then
notarize_obs
fi
cleanup
}
obs-build-main $*

View file

@ -1,11 +0,0 @@
#!/bin/bash
dirty=$(git ls-files --modified)
set +x
if [[ $dirty ]]; then
echo "================================="
echo "Files were not formatted properly"
echo "$dirty"
echo "================================="
exit 1
fi

View file

@ -1,53 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
if [ ${#} -eq 1 -a "${1}" = "VERBOSE" ]; then
VERBOSITY="-l debug"
else
VERBOSITY=""
fi
if [ "${CI}" ]; then
MODE="--check"
else
MODE="-i"
fi
# Runs the formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ ${OS} = "Linux" ]] ; then
NPROC=$(nproc)
elif [[ ${OS} = "Darwin" ]] ; then
NPROC=$(sysctl -n hw.physicalcpu)
fi
# Discover clang-format
if ! type cmake-format 2> /dev/null ; then
echo "Required cmake-format not found"
exit 1
fi
find . -type d \( \
-path ./.deps -o \
-path ./\*build\* -o \
-path ./deps/jansson -o \
-path ./plugins/decklink/\*/decklink-sdk -o \
-path ./plugins/enc-amf -o \
-path ./plugins/mac-syphon/syphon-framework -o \
-path ./plugins/obs-outputs/ftl-sdk -o \
-path ./plugins/obs-vst -o \
-path ./plugins/obs-browser -o \
-path ./plugins/win-dshow/libdshowcapture -o \
-path ./plugins/obs-websocket/deps \
\) -prune -false -type f -o \
-name 'CMakeLists.txt' -or \
-name '*.cmake' \
| xargs -L10 -P ${NPROC} cmake-format ${MODE} ${VERBOSITY}

View file

@ -1,59 +0,0 @@
#!/usr/bin/env bash
# Original source https://github.com/Project-OSRM/osrm-backend/blob/master/scripts/format.sh
set -o errexit
set -o pipefail
set -o nounset
if [ ${#} -eq 1 ]; then
VERBOSITY="--verbose"
else
VERBOSITY=""
fi
# Runs the Clang Formatter in parallel on the code base.
# Return codes:
# - 1 there are files to be formatted
# - 0 everything looks fine
# Get CPU count
OS=$(uname)
NPROC=1
if [[ ${OS} = "Linux" ]] ; then
NPROC=$(nproc)
elif [[ ${OS} = "Darwin" ]] ; then
NPROC=$(sysctl -n hw.physicalcpu)
fi
# Discover clang-format
if type clang-format-13 2> /dev/null ; then
CLANG_FORMAT=clang-format-13
elif type clang-format 2> /dev/null ; then
# Clang format found, but need to check version
CLANG_FORMAT=clang-format
V=$(clang-format --version)
if [[ $V != *"version 13.0"* ]]; then
echo "clang-format is not 13.0 (returned ${V})"
exit 1
fi
else
echo "No appropriate clang-format found (expected clang-format-13.0.0, or clang-format)"
exit 1
fi
find . -type d \( \
-path ./.deps -o \
-path ./\*build\* -o \
-path ./cmake -o \
-path ./plugins/decklink/\*/decklink-sdk -o \
-path ./plugins/enc-amf -o \
-path ./plugins/obs-outputs/ftl-sdk -o \
-path ./plugins/obs-websocket/deps \
\) -prune -false -type f -o \
-name '*.h' -or \
-name '*.hpp' -or \
-name '*.m' -or \
-name '*.mm' -or \
-name '*.c' -or \
-name '*.cpp' \
| xargs -L100 -P ${NPROC} "${CLANG_FORMAT}" ${VERBOSITY} -i -style=file -fallback-style=none

View file

@ -1,84 +0,0 @@
import json
from jsonschema import Draft7Validator
from json_source_map import calculate
from json_source_map.errors import InvalidInputError
import os
import sys
errors = []
def main():
if len(sys.argv) < 2:
print("JSON path required.")
return 1
for filename in sys.argv[1:]:
prep(filename)
try:
with open('validation_errors.json', 'w') as outfile:
json.dump(errors, outfile)
except OSError as e:
print(f'Failed to write validation output to file: {e}')
return 1
if errors:
return 1
return 0
def prep(filename):
try:
with open(filename) as json_file:
json_string = json_file.read()
json_data = json.loads(json_string)
except OSError as e:
print(f'Failed to load file "{filename}": {e}')
return
schema_filename = json_data.get('$schema')
if not schema_filename:
print('File has no schema:', filename)
return
file_path = os.path.split(filename)[0]
schema_file = os.path.join(file_path, schema_filename)
try:
with open(schema_file) as json_file:
schema = json.load(json_file)
except OSError as e:
print(f'Failed to load schema file "{schema_file}": {e}')
return
validate(filename, json_data, json_string, schema)
def validate(filename, json_data, json_string, schema):
try:
servicesPaths = calculate(json_string)
except InvalidInputError as e:
print("Error with file:", e)
return
cls = Draft7Validator(schema)
for e in sorted(cls.iter_errors(json_data), key=str):
print(f'{e}\nIn "{filename}"\n\n')
errorPath = '/'.join(str(v) for v in e.absolute_path)
errorEntry = servicesPaths['/' + errorPath]
errors.append({
"file": filename,
"start_line": errorEntry.value_start.line + 1,
"end_line": errorEntry.value_end.line + 1,
"title": "Validation Error",
"message": e.message,
"annotation_level": "failure"
})
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,363 +0,0 @@
import json
import socket
import ssl
import os
import time
import requests
import sys
import zipfile
from io import BytesIO
from random import randbytes
from urllib.parse import urlparse
from collections import defaultdict
MINIMUM_PURGE_AGE = 9.75 * 24 * 60 * 60 # slightly less than 10 days
TIMEOUT = 10
SKIPPED_SERVICES = {'YouNow', 'SHOWROOM', 'Dacast'}
SERVICES_FILE = 'plugins/rtmp-services/data/services.json'
PACKAGE_FILE = 'plugins/rtmp-services/data/package.json'
CACHE_FILE = 'other/timestamps.json'
GITHUB_OUTPUT_FILE = os.environ.get('GITHUB_OUTPUT', None)
DO_NOT_PING = {'jp9000'}
PR_MESSAGE = '''This is an automatically created pull request to remove unresponsive servers and services.
| Service | Action Taken | Author(s) |
| ------- | ------------ | --------- |
{table}
If you are not responsible for an affected service and want to be excluded from future pings please let us know.
Created by workflow run: https://github.com/{repository}/actions/runs/{run_id}'''
# GQL is great isn't it
GQL_QUERY = '''{
repositoryOwner(login: "obsproject") {
repository(name: "obs-studio") {
object(expression: "master") {
... on Commit {
blame(path: "plugins/rtmp-services/data/services.json") {
ranges {
startingLine
endingLine
commit {
author {
user {
login
}
}
}
}
}
}
}
}
}
}'''
context = ssl.create_default_context()
def check_ftl_server(hostname) -> bool:
"""Check if hostname resolves to a valid address - FTL handshake not implemented"""
try:
socket.getaddrinfo(hostname, 8084, proto=socket.IPPROTO_UDP)
except socket.gaierror as e:
print(f'⚠️ Could not resolve hostname for server: {hostname} (Exception: {e})')
return False
else:
return True
def check_hls_server(uri) -> bool:
"""Check if URL responds with status code < 500 and not 404, indicating that at least there's *something* there"""
try:
r = requests.post(uri, timeout=TIMEOUT)
if r.status_code >= 500 or r.status_code == 404:
raise Exception(f'Server responded with {r.status_code}')
except Exception as e:
print(f'⚠️ Could not connect to HLS server: {uri} (Exception: {e})')
return False
else:
return True
def check_rtmp_server(uri) -> bool:
"""Try connecting and sending a RTMP handshake (with SSL if necessary)"""
parsed = urlparse(uri)
hostname, port = parsed.netloc.partition(':')[::2]
if port:
port = int(port)
elif parsed.scheme == 'rtmps':
port = 443
else:
port = 1935
try:
recv = b''
with socket.create_connection((hostname, port), timeout=TIMEOUT) as sock:
# RTMP handshake is \x03 + 4 bytes time (can be 0) + 4 zero bytes + 1528 bytes random
handshake = b'\x03\x00\x00\x00\x00\x00\x00\x00\x00' + randbytes(1528)
if parsed.scheme == 'rtmps':
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
ssock.sendall(handshake)
while True:
_tmp = ssock.recv(4096)
recv += _tmp
if len(recv) >= 1536 or not _tmp:
break
else:
sock.sendall(handshake)
while True:
_tmp = sock.recv(4096)
recv += _tmp
if len(recv) >= 1536 or not _tmp:
break
if len(recv) < 1536 or recv[0] != 3:
raise ValueError('Invalid RTMP handshake received from server')
except Exception as e:
print(f'⚠️ Connection to server failed: {uri} (Exception: {e})')
return False
else:
return True
def get_last_artifact():
s = requests.session()
s.headers['Authorization'] = f'Bearer {os.environ["GITHUB_TOKEN"]}'
run_id = os.environ['WORKFLOW_RUN_ID']
repo = os.environ['REPOSITORY']
# fetch run first, get workflow id from there to get workflow runs
r = s.get(f'https://api.github.com/repos/{repo}/actions/runs/{run_id}')
r.raise_for_status()
workflow_id = r.json()['workflow_id']
r = s.get(
f'https://api.github.com/repos/{repo}/actions/workflows/{workflow_id}/runs',
params=dict(per_page=1, status='completed', branch='master', conclusion='success', event='schedule'),
)
r.raise_for_status()
runs = r.json()
if not runs['workflow_runs']:
raise ValueError('No completed workflow runs found')
r = s.get(runs['workflow_runs'][0]['artifacts_url'])
r.raise_for_status()
for artifact in r.json()['artifacts']:
if artifact['name'] == 'timestamps':
artifact_url = artifact['archive_download_url']
break
else:
raise ValueError('No previous artifact found.')
r = s.get(artifact_url)
r.raise_for_status()
zip_data = BytesIO()
zip_data.write(r.content)
with zipfile.ZipFile(zip_data) as zip_ref:
for info in zip_ref.infolist():
if info.filename == 'timestamps.json':
return json.loads(zip_ref.read(info.filename))
def find_people_to_blame(raw_services: str, servers: list[tuple[str, str]]) -> dict:
if not servers:
return dict()
# Fetch Blame data from github
s = requests.session()
s.headers['Authorization'] = f'Bearer {os.environ["GITHUB_TOKEN"]}'
r = s.post('https://api.github.com/graphql', json=dict(query=GQL_QUERY, variables=dict()))
r.raise_for_status()
j = r.json()
# The file is only ~2600 lines so this isn't too crazy and makes the lookup very easy
line_author = dict()
for blame in j['data']['repositoryOwner']['repository']['object']['blame']['ranges']:
for i in range(blame['startingLine'] - 1, blame['endingLine']):
if user := blame['commit']['author']['user']:
line_author[i] = user['login']
service_authors = defaultdict(set)
for i, line in enumerate(raw_services.splitlines()):
if '"url":' not in line:
continue
for server, service in servers:
if server in line and (author := line_author.get(i)):
if author not in DO_NOT_PING:
service_authors[service].add(author)
return service_authors
def set_output(name, value):
if not GITHUB_OUTPUT_FILE:
return
try:
with open(GITHUB_OUTPUT_FILE, 'a', encoding='utf-8', newline='\n') as f:
f.write(f'{name}={value}\n')
except Exception as e:
print(f'Writing to github output files failed: {e!r}')
def main():
try:
with open(SERVICES_FILE, encoding='utf-8') as services_file:
raw_services = services_file.read()
services = json.loads(raw_services)
with open(PACKAGE_FILE, encoding='utf-8') as package_file:
package = json.load(package_file)
except OSError as e:
print(f'❌ Could not open services/package file: {e}')
return 1
# attempt to load last check result cache
try:
with open(CACHE_FILE, encoding='utf-8') as check_file:
fail_timestamps = json.load(check_file)
except OSError as e:
# cache might be evicted or not exist yet, so this is non-fatal
print(f'⚠️ Could not read cache file, trying to get last artifact (Exception: {e})')
try:
fail_timestamps = get_last_artifact()
except Exception as e:
print(f'⚠️ Could not fetch cache file, starting fresh. (Exception: {e})')
fail_timestamps = dict()
else:
print('Fetched cache file from last run artifact.')
else:
print('Successfully loaded cache file:', CACHE_FILE)
start_time = int(time.time())
affected_services = dict()
removed_servers = list()
# create temporary new list
new_services = services.copy()
new_services['services'] = []
for service in services['services']:
# skip services that do custom stuff that we can't easily check
if service['name'] in SKIPPED_SERVICES:
new_services['services'].append(service)
continue
service_type = service.get('recommended', {}).get('output', 'rtmp_output')
if service_type not in {'rtmp_output', 'ffmpeg_hls_muxer', 'ftl_output'}:
print('Unknown service type:', service_type)
new_services['services'].append(service)
continue
# create a copy to mess with
new_service = service.copy()
new_service['servers'] = []
# run checks for all the servers, and store results in timestamp cache
for server in service['servers']:
if service_type == 'ftl_output':
is_ok = check_ftl_server(server['url'])
elif service_type == 'ffmpeg_hls_muxer':
is_ok = check_hls_server(server['url'])
else: # rtmp
is_ok = check_rtmp_server(server['url'])
if not is_ok:
if ts := fail_timestamps.get(server['url'], None):
if (delta := start_time - ts) >= MINIMUM_PURGE_AGE:
print(
f'🗑️ Purging server "{server["url"]}", it has been '
f'unresponsive for {round(delta/60/60/24)} days.'
)
removed_servers.append((server['url'], service['name']))
# continuing here means not adding it to the new list, thus dropping it
continue
else:
fail_timestamps[server['url']] = start_time
elif is_ok and server['url'] in fail_timestamps:
# remove timestamp of failed check if server is back
delta = start_time - fail_timestamps[server['url']]
print(f'💡 Server "{server["url"]}" is back after {round(delta/60/60/24)} days!')
del fail_timestamps[server['url']]
new_service['servers'].append(server)
if (diff := len(service['servers']) - len(new_service['servers'])) > 0:
print(f' Removed {diff} server(s) from {service["name"]}')
affected_services[service['name']] = f'{diff} servers removed'
# remove services with no valid servers
if not new_service['servers']:
print(f'💀 Service "{service["name"]}" has no valid servers left, removing!')
affected_services[service['name']] = f'Service removed'
continue
new_services['services'].append(new_service)
# write cache file
try:
os.makedirs('other', exist_ok=True)
with open(CACHE_FILE, 'w', encoding='utf-8') as cache_file:
json.dump(fail_timestamps, cache_file)
except OSError as e:
print(f'❌ Could not write cache file: {e}')
return 1
else:
print('Successfully wrote cache file:', CACHE_FILE)
if removed_servers:
# increment package version and save that as well
package['version'] += 1
package['files'][0]['version'] += 1
try:
with open(SERVICES_FILE, 'w', encoding='utf-8') as services_file:
json.dump(new_services, services_file, indent=4, ensure_ascii=False)
services_file.write('\n')
with open(PACKAGE_FILE, 'w', encoding='utf-8') as package_file:
json.dump(package, package_file, indent=4)
package_file.write('\n')
except OSError as e:
print(f'❌ Could not write services/package file: {e}')
return 1
else:
print(f'Successfully wrote services/package files:\n- {SERVICES_FILE}\n- {PACKAGE_FILE}')
# try to find authors to ping, this is optional and is allowed to fail
try:
service_authors = find_people_to_blame(raw_services, removed_servers)
except Exception as e:
print(f'⚠ Could not fetch blame for some reason: {e}')
service_authors = dict()
# set GitHub outputs
set_output('make_pr', 'true')
msg = PR_MESSAGE.format(
repository=os.environ['REPOSITORY'],
run_id=os.environ['WORKFLOW_RUN_ID'],
table='\n'.join(
'| {name} | {action} | {authors} |'.format(
name=name.replace('|', '\\|'),
action=action,
authors=', '.join(f'@{author}' for author in sorted(service_authors.get(name, []))),
)
for name, action in sorted(affected_services.items())
),
)
set_output('pr_message', json.dumps(msg))
else:
set_output('make_pr', 'false')
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,4 +0,0 @@
brew "cmake"
brew "ccache"
brew "coreutils"
brew "xcbeautify"

View file

@ -1,44 +0,0 @@
#!/bin/bash
##############################################################################
# Linux support functions
##############################################################################
#
# This script file can be included in build scripts for Linux.
#
##############################################################################
# Setup build environment
CI_LINUX_CEF_VERSION=$(cat "${CI_WORKFLOW}" | sed -En "s/[ ]+CEF_BUILD_VERSION_LINUX: '([0-9]+)'/\1/p")
if [ "${TERM-}" -a -z "${CI}" ]; then
COLOR_RED=$(tput setaf 1)
COLOR_GREEN=$(tput setaf 2)
COLOR_BLUE=$(tput setaf 4)
COLOR_ORANGE=$(tput setaf 3)
COLOR_RESET=$(tput sgr0)
else
COLOR_RED=""
COLOR_GREEN=""
COLOR_BLUE=""
COLOR_ORANGE=""
COLOR_RESET=""
fi
if [ "${CI}" -o "${QUIET}" ]; then
export CURLCMD="curl --silent --show-error --location -O"
else
export CURLCMD="curl --progress-bar --location --continue-at - -O"
fi
_add_ccache_to_path() {
if [ "${CMAKE_CCACHE_OPTIONS}" ]; then
PATH="/usr/local/opt/ccache/libexec:${PATH}"
status "Compiler Info:"
local IFS=$'\n'
for COMPILER_INFO in $(type cc c++ gcc g++ clang clang++ || true); do
info "${COMPILER_INFO}"
done
fi
}

View file

@ -1,156 +0,0 @@
#!/bin/bash
##############################################################################
# macOS support functions
##############################################################################
#
# This script file can be included in build scripts for macOS.
#
##############################################################################
# Setup build environment
WORKFLOW_CONTENT=$(/bin/cat "${CI_WORKFLOW}")
MACOS_VERSION="$(/usr/bin/sw_vers -productVersion)"
MACOS_MAJOR="$(echo ${MACOS_VERSION} | /usr/bin/cut -d '.' -f 1)"
MACOS_MINOR="$(echo ${MACOS_VERSION} | /usr/bin/cut -d '.' -f 2)"
if [ "${TERM-}" -a -z "${CI}" ]; then
COLOR_RED=$(/usr/bin/tput setaf 1)
COLOR_GREEN=$(/usr/bin/tput setaf 2)
COLOR_BLUE=$(/usr/bin/tput setaf 4)
COLOR_ORANGE=$(/usr/bin/tput setaf 3)
COLOR_RESET=$(/usr/bin/tput sgr0)
else
COLOR_RED=""
COLOR_GREEN=""
COLOR_BLUE=""
COLOR_ORANGE=""
COLOR_RESET=""
fi
## DEFINE UTILITIES ##
check_macos_version() {
ARCH="${ARCH:-${CURRENT_ARCH}}"
case "${ARCH}" in
x86_64) ;;
arm64) ;;
*) caught_error "Unsupported architecture '${ARCH}' provided" ;;
esac
step "Check macOS version..."
MIN_VERSION="11.0"
MIN_MAJOR=$(echo ${MIN_VERSION} | /usr/bin/cut -d '.' -f 1)
MIN_MINOR=$(echo ${MIN_VERSION} | /usr/bin/cut -d '.' -f 2)
if [ "${MACOS_MAJOR}" -lt "11" -a "${MACOS_MINOR}" -lt "${MIN_MINOR}" ]; then
error "ERROR: Minimum required macOS version is ${MIN_VERSION}, but running on ${MACOS_VERSION}"
fi
export CODESIGN_LINKER="ON"
}
install_homebrew_deps() {
if ! exists brew; then
caught_error "Homebrew not found - please install Homebrew (https://brew.sh)"
fi
brew bundle --file "${CHECKOUT_DIR}/CI/include/Brewfile" ${QUIET:+--quiet}
check_curl
}
check_curl() {
if [ "${MACOS_MAJOR}" -lt "11" -a "${MACOS_MINOR}" -lt "15" ]; then
if [ ! -d /usr/local/opt/curl ]; then
step "Install Homebrew curl..."
brew install curl
fi
CURLCMD="/usr/local/opt/curl/bin/curl"
else
CURLCMD="curl"
fi
if [ "${CI}" -o "${QUIET}" ]; then
export CURLCMD="${CURLCMD} --silent --show-error --location -O"
else
export CURLCMD="${CURLCMD} --progress-bar --location --continue-at - -O"
fi
}
check_archs() {
step "Check Architecture..."
ARCH="${ARCH:-${CURRENT_ARCH}}"
if [ "${ARCH}" = "universal" ]; then
CMAKE_ARCHS="x86_64;arm64"
elif [ "${ARCH}" != "x86_64" -a "${ARCH}" != "arm64" ]; then
caught_error "Unsupported architecture '${ARCH}' provided"
else
CMAKE_ARCHS="${ARCH}"
fi
}
_add_ccache_to_path() {
if [ "${CMAKE_CCACHE_OPTIONS}" ]; then
if [ "${CURRENT_ARCH}" == "arm64" ]; then
PATH="/opt/homebrew/opt/ccache/libexec:${PATH}"
else
PATH="/usr/local/opt/ccache/libexec:${PATH}"
fi
status "Compiler Info:"
local IFS=$'\n'
for COMPILER_INFO in $(type cc c++ gcc g++ clang clang++ || true); do
info "${COMPILER_INFO}"
done
fi
}
## SET UP CODE SIGNING AND NOTARIZATION CREDENTIALS ##
##############################################################################
# Apple Developer Identity needed:
#
# + Signing the code requires a developer identity in the system's keychain
# + codesign will look up and find the identity automatically
#
##############################################################################
read_codesign_ident() {
if [ -z "${CODESIGN_IDENT}" ]; then
step "Set up code signing..."
read -p "${COLOR_ORANGE} + Apple developer identity: ${COLOR_RESET}" CODESIGN_IDENT
fi
CODESIGN_IDENT_SHORT=$(echo "${CODESIGN_IDENT}" | /usr/bin/sed -En "s/.+\((.+)\)/\1/p")
}
##############################################################################
# Apple Developer credentials necessary:
#
# + Signing for distribution and notarization require an active Apple
# Developer membership
# + An Apple Development identity is needed for code signing
# (i.e. 'Apple Development: YOUR APPLE ID (PROVIDER)')
# + Your Apple developer ID is needed for notarization
# + An app-specific password is necessary for notarization from CLI
# + This password will be stored in your macOS keychain under the identifier
# 'OBS-Codesign-Password' with access Apple's 'notarytool' only.
##############################################################################
read_codesign_pass() {
step "Set up notarization..."
if [ -z "${CODESIGN_IDENT_USER}" ]; then
read -p "${COLOR_ORANGE} + Apple account id: ${COLOR_RESET}" CODESIGN_IDENT_USER
fi
if [ -z "${CODESIGN_IDENT_PASS}" ]; then
CODESIGN_IDENT_PASS=$(stty -echo; read -p "${COLOR_ORANGE} + Apple developer password: ${COLOR_RESET}" secret; stty echo; echo $secret)
echo ""
fi
step "Update notarization keychain..."
echo -n "${COLOR_ORANGE}"
/usr/bin/xcrun notarytool store-credentials "OBS-Codesign-Password" --apple-id "${CODESIGN_IDENT_USER}" --team-id "${CODESIGN_IDENT_SHORT}" --password "${CODESIGN_IDENT_PASS}"
echo -n "${COLOR_RESET}"
}

View file

@ -1,152 +0,0 @@
#!/bin/bash
##############################################################################
# Linux dependency management function
##############################################################################
#
# This script file can be included in build scripts for Linux or run directly
# with the -s/--standalone switch
#
##############################################################################
# Halt on errors
set -eE
install_build-deps() {
shift
status "Install OBS build dependencies"
trap "caught_error 'install_build-deps'" ERR
sudo apt-get install --no-install-recommends -y $@
}
install_obs-deps() {
shift
status "Install OBS dependencies"
trap "caught_error 'install_obs-deps'" ERR
if [ -z "${DISABLE_PIPEWIRE}" ]; then
sudo apt-get install --no-install-recommends -y $@ libpipewire-0.3-dev
else
sudo apt-get install --no-install-recommends -y $@
fi
}
install_qt5-deps() {
shift
status "Install Qt5 dependencies"
trap "caught_error 'install_qt5-deps'" ERR
_QT6_AVAILABLE="$(sudo apt-cache madison qt6-base-dev)"
if [ -z "${_QT6_AVAILABLE}" ]; then
sudo apt-get install --no-install-recommends -y $@
fi
}
install_qt6-deps() {
shift
status "Install Qt6 dependencies"
trap "caught_error 'install_qt6-deps'" ERR
_QT6_AVAILABLE="$(sudo apt-cache madison ${1})"
if [ "${_QT6_AVAILABLE}" ]; then
sudo apt-get install --no-install-recommends -y $@
fi
}
install_cef() {
shift
status "Setup for dependency CEF v${1}"
ensure_dir "${DEPS_BUILD_DIR}"
if [ "${CI}" -a "${RESTORED_CEF}" ]; then
_SKIP=TRUE
elif [ -d "${DEPS_BUILD_DIR}/cef_binary_${1}_linux64" -a -f "${DEPS_BUILD_DIR}/cef_binary_${1}_linux64/build/libcef_dll_wrapper/libcef_dll_wrapper.a" ]; then
_SKIP=TRUE
fi
if [ -z "${_SKIP}" ]; then
step "Download..."
${CURLCMD:-curl -O} https://cdn-fastly.obsproject.com/downloads/cef_binary_${1}_linux64.tar.bz2
step "Unpack..."
tar -xf cef_binary_${1}_linux64.tar.bz2
else
step "Found existing Chromium Embedded Framework and loader library..."
fi
}
install_plugin-deps() {
shift
status "Install plugin dependencies"
trap "caught_error 'install_plugin-deps'" ERR
sudo apt-get install --no-install-recommends -y $@
}
install_dependencies() {
status "Set up apt"
trap "caught_error 'install_dependencies'" ERR
BUILD_DEPS=(
"build-deps cmake ninja-build pkg-config clang clang-format build-essential curl ccache"
"obs-deps libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswresample-dev \
libswscale-dev libx264-dev libcurl4-openssl-dev libmbedtls-dev libgl1-mesa-dev libjansson-dev \
libluajit-5.1-dev python3-dev libx11-dev libxcb-randr0-dev libxcb-shm0-dev libxcb-xinerama0-dev \
libxcb-composite0-dev libxinerama-dev libxcb1-dev libx11-xcb-dev libxcb-xfixes0-dev swig libcmocka-dev \
libpci-dev libxss-dev libglvnd-dev libgles2-mesa libgles2-mesa-dev libwayland-dev \
libxkbcommon-dev"
"qt5-deps qtbase5-dev qtbase5-private-dev libqt5svg5-dev qtwayland5"
"qt6-deps qt6-base-dev qt6-base-private-dev libqt6svg6-dev qt6-wayland"
"cef ${LINUX_CEF_BUILD_VERSION:-${CI_LINUX_CEF_VERSION}}"
"plugin-deps libasound2-dev libfdk-aac-dev libfontconfig-dev libfreetype6-dev libjack-jackd2-dev \
libpulse-dev libsndio-dev libspeexdsp-dev libudev-dev libv4l-dev libva-dev libvlc-dev libdrm-dev \
nlohmann-json3-dev libwebsocketpp-dev libasio-dev libvpl-dev libqrcodegencpp-dev"
)
sudo apt-get -qq update
for DEPENDENCY in "${BUILD_DEPS[@]}"; do
set -- ${DEPENDENCY}
trap "caught_error ${DEPENDENCY}" ERR
FUNC_NAME="install_${1}"
${FUNC_NAME} ${@}
done
}
install-dependencies-standalone() {
CHECKOUT_DIR="$(/usr/bin/git rev-parse --show-toplevel)"
PRODUCT_NAME="OBS-Studio"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_linux.sh"
status "Setup of OBS build dependencies"
install_dependencies
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"--disable-pipewire : Disable building with PipeWire support (default: off)\n"
}
install-dependencies-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
--disable-pipewire ) DISABLE_PIPEWIRE=TRUE; shift ;;
-- ) shift; break ;;
* ) break ;;
esac
done
install-dependencies-standalone
fi
}
install-dependencies-main $*

View file

@ -1,135 +0,0 @@
#!/bin/bash
##############################################################################
# Linux build function
##############################################################################
#
# This script file can be included in build scripts for Linux or run directly
#
##############################################################################
# Halt on errors
set -eE
build_obs() {
status "Build OBS"
trap "caught_error 'build app'" ERR
if [ -z "${CI}" ]; then
_backup_artifacts
fi
step "Configure OBS..."
_configure_obs
ensure_dir "${CHECKOUT_DIR}/"
step "Build OBS targets..."
cmake --build ${BUILD_DIR}
}
# Function to configure OBS build
_configure_obs() {
ensure_dir "${CHECKOUT_DIR}"
status "Configuration of OBS build system..."
trap "caught_error 'configure build'" ERR
check_ccache
if [ "${TWITCH_CLIENTID}" -a "${TWITCH_HASH}" ]; then
TWITCH_OPTIONS="-DTWITCH_CLIENTID='${TWITCH_CLIENTID}' -DTWITCH_HASH='${TWITCH_HASH}'"
fi
if [ "${RESTREAM_CLIENTID}" -a "${RESTREAM_HASH}" ]; then
RESTREAM_OPTIONS="-DRESTREAM_CLIENTID='${RESTREAM_CLIENTID}' -DRESTREAM_HASH='${RESTREAM_HASH}'"
fi
if [ "${YOUTUBE_CLIENTID}" -a "${YOUTUBE_CLIENTID_HASH}" -a "${YOUTUBE_SECRET}" -a "{YOUTUBE_SECRET_HASH}" ]; then
YOUTUBE_OPTIONS="-DYOUTUBE_CLIENTID='${YOUTUBE_CLIENTID}' -DYOUTUBE_CLIENTID_HASH='${YOUTUBE_CLIENTID_HASH}' -DYOUTUBE_SECRET='${YOUTUBE_SECRET}' -DYOUTUBE_SECRET_HASH='${YOUTUBE_SECRET_HASH}'"
fi
if [ "${PORTABLE}" ]; then
PORTABLE_BUILD="ON"
fi
if [ "${DISABLE_PIPEWIRE}" ]; then
PIPEWIRE_OPTION="-DENABLE_PIPEWIRE=OFF"
fi
if [ "${DISABLE_QSV}" ]; then
QSV_OPTION="-DENABLE_QSV11=OFF"
fi
cmake -S . -B ${BUILD_DIR} -G Ninja \
-DCEF_ROOT_DIR="${DEPS_BUILD_DIR}/cef_binary_${LINUX_CEF_BUILD_VERSION:-${CI_LINUX_CEF_VERSION}}_linux64" \
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG} \
-DLINUX_PORTABLE=${PORTABLE_BUILD:-OFF} \
-DENABLE_AJA=OFF \
-DENABLE_NEW_MPEGTS_OUTPUT=OFF \
-DENABLE_WEBRTC=OFF \
${PIPEWIRE_OPTION} \
${QSV_OPTION} \
${YOUTUBE_OPTIONS} \
${TWITCH_OPTIONS} \
${RESTREAM_OPTIONS} \
${CI:+-DENABLE_UNIT_TESTS=ON -DBUILD_FOR_DISTRIBUTION=${BUILD_FOR_DISTRIBUTION} -DOBS_BUILD_NUMBER=${GITHUB_RUN_ID}} \
${QUIET:+-Wno-deprecated -Wno-dev --log-level=ERROR}
}
# Function to backup previous build artifacts
_backup_artifacts() {
ensure_dir "${CHECKOUT_DIR}"
if [ -d ${BUILD_DIR} ]; then
status "Backup of old OBS build artifacts"
CUR_DATE=$(date +"%Y-%m-%d@%H%M%S")
NIGHTLY_DIR="${CHECKOUT_DIR}/nightly-${CUR_DATE}"
PACKAGE_NAME=$(find ${BUILD_DIR} -maxdepth 1 -name "*.deb" | sort -rn | head -1)
if [ "${PACKAGE_NAME}" ]; then
step "Back up $(basename "${PACKAGE_NAME}")..."
ensure_dir "${NIGHTLY_DIR}"
mv "../${BUILD_DIR}/$(basename "${PACKAGE_NAME}")" ${NIGHTLY_DIR}/
info "You can find ${PACKAGE_NAME} in ${NIGHTLY_DIR}"
fi
fi
}
build-obs-standalone() {
CHECKOUT_DIR="$(git rev-parse --show-toplevel)"
PRODUCT_NAME="OBS-Studio"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_linux.sh"
build_obs
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-p, --portable : Create portable build (default: off)\n" \
"--disable-pipewire : Disable building with PipeWire support (default: off)\n" \
"--build-dir : Specify alternative build directory (default: build)\n"
}
build-obs-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-p | --portable ) export PORTABLE=TRUE; shift ;;
--disable-pipewire ) DISABLE_PIPEWIRE=TRUE; shift ;;
--disable-qsv ) DISABLE_QSV=TRUE; shift ;;
--build-dir ) BUILD_DIR="${2}"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
build-obs-standalone
fi
}
build-obs-main $*

View file

@ -1,90 +0,0 @@
#!/bin/bash
##############################################################################
# Linux libobs plugin package function
##############################################################################
#
# This script file can be included in build scripts for Linux or run directly
#
##############################################################################
# Halt on errors
set -eE
package_obs() {
status "Create Linux debian package"
trap "caught_error 'package app'" ERR
ensure_dir "${CHECKOUT_DIR}"
step "Package OBS..."
cmake --build ${BUILD_DIR} -t package
DEB_NAME=$(find ${BUILD_DIR} -maxdepth 1 -type f -name "obs*.deb" | sort -rn | head -1)
DEBUG_NAME="${DEB_NAME//.deb/-dbgsym.ddeb}"
if [ "${DEB_NAME}" ]; then
mv "${DEB_NAME}" "${BUILD_DIR}/${FILE_NAME}"
if [ "${DEBUG_NAME}" ]; then
mv "${DEBUG_NAME}" "${BUILD_DIR}/${FILE_NAME//.deb/-dbgsym.ddeb}"
fi
else
error "ERROR No suitable OBS debian package generated"
fi
}
package-obs-standalone() {
PRODUCT_NAME="OBS-Studio"
CHECKOUT_DIR="$(git rev-parse --show-toplevel)"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_linux.sh"
if [ -z "${CI}" ]; then
step "Fetch OBS tags..."
git fetch --tags origin
fi
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
GIT_HASH=$(git rev-parse --short=9 HEAD)
GIT_TAG=$(git describe --tags --abbrev=0)
UBUNTU_VERSION=$(lsb_release -sr)
if [ "${BUILD_FOR_DISTRIBUTION}" = "true" ]; then
VERSION_STRING="${GIT_TAG}"
else
VERSION_STRING="${GIT_TAG}-${GIT_HASH}"
fi
FILE_NAME="obs-studio-${VERSION_STRING}-ubuntu-${UBUNTU_VERSION}.deb"
package_obs
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"--build-dir : Specify alternative build directory (default: build)\n"
}
package-obs-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
--build-dir ) BUILD_DIR="${2}"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
package-obs-standalone
fi
}
package-obs-main $*

View file

@ -1,60 +0,0 @@
#!/bin/bash
##############################################################################
# macOS dependency management function
##############################################################################
#
# This script file can be included in build scripts for macOS or run directly.
#
##############################################################################
# Halt on errors
set -eE
install_dependencies() {
status "Install Homebrew dependencies"
trap "caught_error 'install_dependencies'" ERR
install_homebrew_deps
}
install-dependencies-standalone() {
CHECKOUT_DIR="$(/usr/bin/git rev-parse --show-toplevel)"
PRODUCT_NAME="OBS-Studio"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_macos.sh"
status "Setup of OBS build dependencies"
check_macos_version
check_archs
install_dependencies
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-a, --architecture : Specify build architecture (default: x86_64, alternative: arm64)\n"
}
install-dependencies-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-a | --architecture ) ARCH="${2}"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
install-dependencies-standalone
fi
}
install-dependencies-main $*

View file

@ -1,147 +0,0 @@
#!/bin/bash
##############################################################################
# macOS build function
##############################################################################
#
# This script file can be included in build scripts for macOS or run directly
#
##############################################################################
# Halt on errors
set -eE
build_obs() {
status "Build OBS"
trap "caught_error 'build app'" ERR
step "Configure OBS..."
_configure_obs
ensure_dir "${CHECKOUT_DIR}/"
step "Build OBS targets..."
export NSUnbufferedIO=YES
: "${PACKAGE:=}"
case "${GITHUB_EVENT_NAME}" in
push) if [[ ${GITHUB_REF_NAME} =~ [0-9]+.[0-9]+.[0-9]+(-(rc|beta).+)? ]]; then PACKAGE=1; fi ;;
pull_request) PACKAGE=1 ;;
esac
pushd "build_macos" > /dev/null
if [[ "${PACKAGE}" && "${CODESIGN_IDENT:--}" != '-' ]]; then
set -o pipefail && xcodebuild ONLY_ACTIVE_ARCH=NO -archivePath "obs-studio.xcarchive" -scheme obs-studio -destination "generic/platform=macOS,name=Any Mac" -parallelizeTargets -hideShellScriptEnvironment archive 2>&1 | xcbeautify
set -o pipefail && xcodebuild -exportArchive -archivePath "obs-studio.xcarchive" -exportOptionsPlist "exportOptions.plist" -exportPath "." 2>&1 | xcbeautify
else
set -o pipefail && xcodebuild ONLY_ACTIVE_ARCH=NO -project obs-studio.xcodeproj -target obs-studio -destination "generic/platform=macOS,name=Any Mac" -parallelizeTargets -configuration RelWithDebInfo -hideShellScriptEnvironment build 2>&1 | xcbeautify
rm -rf OBS.app && mkdir OBS.app
ditto UI/RelWithDebInfo/OBS.app OBS.app
fi
popd > /dev/null
unset NSUnbufferedIO
}
bundle_obs() {
status "Create relocatable macOS application bundle"
trap "caught_error 'package app'" ERR
ensure_dir "${CHECKOUT_DIR}"
step "Install OBS application bundle..."
find "build_macos/UI/${BUILD_CONFIG}" -type d -name "OBS.app" | xargs -I{} cp -r {} "build_${ARCH}"/
}
# Function to configure OBS build
_configure_obs() {
if [ "${CODESIGN}" ]; then
read_codesign_ident
fi
ensure_dir "${CHECKOUT_DIR}"
status "Configure OBS build system..."
trap "caught_error 'configure build'" ERR
check_ccache
if [ "${SPARKLE_APPCAST_URL}" -a "${SPARKLE_PUBLIC_KEY}" ]; then
SPARKLE_OPTIONS="-DSPARKLE_APPCAST_URL=\"${SPARKLE_APPCAST_URL}\" -DSPARKLE_PUBLIC_KEY=\"${SPARKLE_PUBLIC_KEY}\""
fi
PRESET="macos"
if [ "${CI}" ]; then
case "${GITHUB_EVENT_NAME}" in
push)
if [ "${GITHUB_REF_TYPE}" != 'tag' ]; then
PRESET="macos-ci"
fi
;;
*) PRESET="macos-ci" ;;
esac
fi
cmake -S . --preset ${PRESET} \
-DCMAKE_OSX_ARCHITECTURES=${ARCH} \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install \
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG} \
-DOBS_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}" \
-DOBS_CODESIGN_TEAM="${CODESIGN_TEAM:-}" \
-DOBS_PROVISIONING_PROFILE="${PROVISIONING_PROFILE:-}" \
${YOUTUBE_OPTIONS} \
${TWITCH_OPTIONS} \
${RESTREAM_OPTIONS} \
${SPARKLE_OPTIONS} \
${QUIET:+-Wno-deprecated -Wno-dev --log-level=ERROR}
}
build-obs-standalone() {
CHECKOUT_DIR="$(/usr/bin/git rev-parse --show-toplevel)"
PRODUCT_NAME="OBS-Studio"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_macos.sh"
check_archs
check_macos_version
build_obs
if [ "${BUNDLE}" ]; then
bundle_obs
fi
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-a, --architecture : Specify build architecture (default: x86_64, alternative: arm64)\n" \
"-c, --codesign : Codesign OBS and all libraries (default: ad-hoc only)\n" \
"-b, --bundle : Create relocatable OBS application bundle in build directory (default: build/install/OBS.app)\n"
}
build-obs-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-a | --architecture ) ARCH="${2}"; shift 2 ;;
-c | --codesign ) CODESIGN=TRUE; shift ;;
-b | --bundle ) BUNDLE=TRUE; shift ;;
-- ) shift; break ;;
* ) break ;;
esac
done
build-obs-standalone
fi
}
build-obs-main $*

View file

@ -1,184 +0,0 @@
#!/bin/bash
##############################################################################
# macOS libobs plugin package function
##############################################################################
#
# This script file can be included in build scripts for macOS or run directly
#
##############################################################################
# Halt on errors
set -eE
package_obs() {
if [ "${CODESIGN}" ]; then
read_codesign_ident
fi
status "Create macOS disk image"
trap "caught_error 'package app'" ERR
ensure_dir "${CHECKOUT_DIR}"
step "Package OBS..."
BUILD_DIR="build_macos"
root_dir="$(pwd)"
pushd "${BUILD_DIR}" > /dev/null > /dev/null
mkdir -p "${FILE_NAME//.dmg/}/.background"
cp "${root_dir}/cmake/macos/resources/background.tiff" "${FILE_NAME//.dmg/}/.background/"
cp "${root_dir}/cmake/macos/resources/AppIcon.icns" "${FILE_NAME//.dmg/}/.VolumeIcon.icns"
ln -s /Applications "${FILE_NAME//.dmg/}/Applications"
mkdir -p "${FILE_NAME//.dmg/}/OBS.app"
ditto OBS.app "${FILE_NAME//.dmg/}/OBS.app"
hdiutil create -volname "${FILE_NAME//.dmg/}" -srcfolder "${FILE_NAME//.dmg/}" -ov -fs APFS -format UDRW temp.dmg
hdiutil attach -noverify -readwrite temp.dmg
SetFile -c icnC /Volumes/"${FILE_NAME//.dmg/}"/.VolumeIcon.icns
SetFile -a C /Volumes/"${FILE_NAME//.dmg/}"
osascript package.applescript "${FILE_NAME//.dmg/}"
hdiutil detach "/Volumes/${FILE_NAME//.dmg/}"
hdiutil convert -format ULMO -o "${FILE_NAME}" temp.dmg
rm temp.dmg
step "Codesign OBS disk image..."
/usr/bin/codesign --force --sign "${CODESIGN_IDENT:--}" "${FILE_NAME}"
rm -rf "${FILE_NAME//.dmg/}"
popd > /dev/null
}
notarize_obs() {
status "Notarize OBS"
trap "caught_error 'notarizing app'" ERR
if ! exists brew; then
error "ERROR Homebrew not found - please install homebrew (https://brew.sh)"
exit 1
fi
ensure_dir "${CHECKOUT_DIR}"
if [ "${NOTARIZE_IMAGE}" ]; then
trap "_caught_error_hdiutil_verify '${NOTARIZE_IMAGE}'" ERR
step "Verify OBS disk image ${NOTARIZE_IMAGE}..."
hdiutil verify "${NOTARIZE_IMAGE}"
NOTARIZE_TARGET="${NOTARIZE_IMAGE}"
elif [ "${NOTARIZE_BUNDLE}" ]; then
NOTARIZE_TARGET="${NOTARIZE_BUNDLE}"
else
OBS_IMAGE="${BUILD_DIR}/${FILE_NAME}"
if [ -f "${OBS_IMAGE}" ]; then
NOTARIZE_TARGET="${OBS_IMAGE}"
else
error "No notarization application bundle ('OBS.app') or disk image ('${NOTARIZE_IMAGE:-${FILE_NAME}}') found"
return
fi
fi
if [ "$?" -eq 0 ]; then
read_codesign_ident
read_codesign_pass
step "Notarize ${NOTARIZE_TARGET}..."
/usr/bin/xcrun notarytool submit "${NOTARIZE_TARGET}" --keychain-profile "OBS-Codesign-Password" --wait
step "Staple the ticket to ${NOTARIZE_TARGET}..."
/usr/bin/xcrun stapler staple "${NOTARIZE_TARGET}"
fi
}
_caught_error_hdiutil_verify() {
error "ERROR during verifying image '${1}'"
cleanup
exit 1
}
package-obs-standalone() {
PRODUCT_NAME="OBS-Studio"
CHECKOUT_DIR="$(/usr/bin/git rev-parse --show-toplevel)"
DEPS_BUILD_DIR="${CHECKOUT_DIR}/../obs-build-dependencies"
source "${CHECKOUT_DIR}/CI/include/build_support.sh"
source "${CHECKOUT_DIR}/CI/include/build_support_macos.sh"
check_archs
check_macos_version
if [ -z "${CI}" ]; then
step "Fetch OBS tags..."
/usr/bin/git fetch --tags origin
fi
GIT_BRANCH=$(/usr/bin/git rev-parse --abbrev-ref HEAD)
GIT_HASH=$(/usr/bin/git rev-parse --short=9 HEAD)
GIT_TAG=$(/usr/bin/git describe --tags --abbrev=0)
if [ "${BUILD_FOR_DISTRIBUTION}" ]; then
VERSION_STRING="${GIT_TAG}"
else
VERSION_STRING="${GIT_TAG}-${GIT_HASH}"
fi
if [ -z "${NOTARIZE_IMAGE}" -a -z "${NOTARIZE_BUNDLE}" ]; then
if [ "${ARCH}" = "arm64" ]; then
FILE_NAME="obs-studio-${VERSION_STRING}-macos-arm64.dmg"
elif [ "${ARCH}" = "universal" ]; then
FILE_NAME="obs-studio-${VERSION_STRING}-macos.dmg"
else
FILE_NAME="obs-studio-${VERSION_STRING}-macos-x86_64.dmg"
fi
package_obs
fi
if [ "${NOTARIZE}" ]; then
notarize_obs
fi
}
print_usage() {
echo -e "Usage: ${0}\n" \
"-h, --help : Print this help\n" \
"-q, --quiet : Suppress most build process output\n" \
"-v, --verbose : Enable more verbose build process output\n" \
"-a, --architecture : Specify build architecture (default: x86_64, alternative: arm64)\n" \
"-c, --codesign : Codesign OBS and all libraries (default: ad-hoc only)\n" \
"-n, --notarize : Notarize OBS (default: off)\n" \
"--notarize-image [IMAGE] : Specify existing OBS disk image for notarization\n" \
"--notarize-bundle [BUNDLE] : Specify existing OBS application bundle for notarization\n" \
"--build-dir : Specify alternative build directory (default: build)\n"
}
package-obs-main() {
if [ -z "${_RUN_OBS_BUILD_SCRIPT}" ]; then
while true; do
case "${1}" in
-h | --help ) print_usage; exit 0 ;;
-q | --quiet ) export QUIET=TRUE; shift ;;
-v | --verbose ) export VERBOSE=TRUE; shift ;;
-a | --architecture ) ARCH="${2}"; shift 2 ;;
-c | --codesign ) CODESIGN=TRUE; shift ;;
-n | --notarize ) NOTARIZE=TRUE; CODESIGN=TRUE; shift ;;
--build-dir ) BUILD_DIR="${2}"; shift 2 ;;
--notarize-image ) NOTARIZE_IMAGE="${2}"; NOTARIZE=TRUE; CODESIGN=TRUE; shift 2 ;;
--notarize-bundle ) NOTARIZE_BUNDLE="${2}"; NOTARIZE=TRUE; CODESIGN=TRUE; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
package-obs-standalone
fi
}
package-obs-main $*

View file

@ -1,36 +0,0 @@
"AppBuild"
{
"AppID" "1905180"
"Desc" "github_@@DESC@@"
"ContentRoot" "./"
"BuildOutput" "build/"
"SetLive" "@@BRANCH@@"
"Depots"
{
"1905181" // Windows
{
"ContentRoot" "./steam-windows"
"InstallScript" "scripts/installscript.vdf"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
}
"1905182" // Mac
{
"ContentRoot" "./steam-macos"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
}
}
}

View file

@ -1,35 +0,0 @@
"AppBuild"
{
"AppID" "1905640"
"Desc" "github_@@DESC@@"
"ContentRoot" "./"
"BuildOutput" "build/"
"SetLive" "@@BRANCH@@"
"Depots"
{
"1905642" // Windows
{
"ContentRoot" "./steam-windows"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
}
"1905641" // Mac
{
"ContentRoot" "./steam-macos"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
}
}
}

View file

@ -1,14 +0,0 @@
#!/bin/zsh
arch_name="${CPUTYPE}"
is_translated="$(sysctl -in sysctl.proc_translated)"
if (( is_translated )) arch_name="arm64"
if [[ ${@} == *'--intel'* ]] arch_name="x86_64"
if [[ -d OBS.app ]] exec open OBS.app -W --args "${@}"
case ${arch_name} {
x86_64) exec open x86_64/OBS.app -W --args "${@}" ;;
arm64) exec open arm64/OBS.app -W --args "${@}" ;;
*) echo "Unknown architecture: ${arch_name}"; exit 2 ;;
}

View file

@ -1,85 +0,0 @@
@echo off
@cd /d "%~dp0"
goto checkAdmin
:checkAdmin
net session >nul 2>&1
if %errorLevel% == 0 (
echo.
) else (
echo Administrative rights are required. Please re-run this script as Administrator.
goto end
)
:writeRegistry
reg add "HKLM\SOFTWARE\OBS Studio" /f /t REG_SZ /d %1 /reg:32
reg add "HKLM\SOFTWARE\OBS Studio" /f /t REG_SZ /d %1 /reg:64
:setupProgramData
:: Required for UWP applications
mkdir "%PROGRAMDATA%\obs-studio-hook"
icacls "%PROGRAMDATA%\obs-studio-hook" /grant "ALL APPLICATION PACKAGES":(OI)(CI)(GR,GE)
:checkDLL
echo Checking for 32-bit Virtual Cam registration...
reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:32
if %errorLevel% == 0 (
echo 32-bit Virtual Cam found, skipping install...
echo.
) else (
echo 32-bit Virtual Cam not found, installing...
goto install32DLL
)
:CheckDLLContinue
echo Checking for 64-bit Virtual Cam registration...
reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:64
if %errorLevel% == 0 (
echo 64-bit Virtual Cam found, skipping install...
echo.
) else (
echo 64-bit Virtual Cam not found, installing...
goto install64DLL
)
goto endSuccess
:install32DLL
echo Installing 32-bit Virtual Cam...
regsvr32.exe /i /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll
reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:32
if %errorLevel% == 0 (
echo 32-bit Virtual Cam successfully installed
echo.
) else (
echo 32-bit Virtual Cam installation failed
echo.
goto endFail
)
goto checkDLLContinue
:install64DLL
echo Installing 64-bit Virtual Cam...
regsvr32.exe /i /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module64.dll
reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:64
if %errorLevel% == 0 (
echo 64-bit Virtual Cam successfully installed
echo.
goto endSuccess
) else (
echo 64-bit Virtual Cam installation failed
echo.
goto endFail
)
:endFail
echo Something failed, please report this on the OBS Discord or Forums!
goto end
:endSuccess
echo Virtual Cam installed!
echo.
:end
exit

View file

@ -1,20 +0,0 @@
"InstallScript"
{
"Run Process"
{
"install"
{
"process 1" "scripts\\install.bat"
"command 1" "\"%INSTALLDIR%\""
}
}
"Run Process On Uninstall"
{
"uninstall"
{
"process 1" "scripts\\uninstall.bat"
"command 1" "\"%INSTALLDIR%\""
}
}
}

View file

@ -1,33 +0,0 @@
@echo off
@cd /d "%~dp0"
goto checkAdmin
:checkAdmin
net session >nul 2>&1
if %errorLevel% == 0 (
echo.
) else (
echo Administrative rights are required. Please re-run this script as Administrator.
goto end
)
:clearRegistry
reg delete "HKLM\SOFTWARE\OBS Studio" /f /reg:32
reg delete "HKLM\SOFTWARE\OBS Studio" /f /reg:64
:: Vulkan layer keys
reg delete "HKLM\SOFTWARE\Khronos\Vulkan\ImplicitLayers" /f /v "%PROGRAMDATA%\obs-studio-hook\obs-vulkan64.json" /reg:32
reg delete "HKLM\SOFTWARE\Khronos\Vulkan\ImplicitLayers" /f /v "%PROGRAMDATA%\obs-studio-hook\obs-vulkan32.json" /reg:64
:deleteProgramDataFolder
RMDIR /S /Q "%PROGRAMDATA%\obs-studio-hook"
:uninstallDLLs
regsvr32.exe /u /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll
regsvr32.exe /u /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module64.dll
:endSuccess
echo Virtual Cam uninstalled!
echo.
:end
exit