CI: Add zsh-based build framework files for macOS

This commit is contained in:
PatTheMav 2023-02-02 22:20:03 +01:00
parent c33fa8bfa2
commit 1cfa06a2aa
No known key found for this signature in database
31 changed files with 554 additions and 100 deletions

5
.github/scripts/.Brewfile vendored Normal file
View File

@ -0,0 +1,5 @@
brew "ccache"
brew "cmake"
brew "git"
brew "jq"
brew "xcbeautify"

22
.github/scripts/utils.zsh/check_macos vendored Normal file
View File

@ -0,0 +1,22 @@
autoload -Uz is-at-least log_group log_info log_error log_status
local macos_version=$(sw_vers -productVersion)
log_group 'Install macOS build requirements'
log_info 'Checking macOS version...'
if ! is-at-least 11.0 ${macos_version}; then
log_error "Minimum required macOS version is 11.0, but running on macOS ${macos_version}"
return 2
else
log_status "macOS ${macos_version} is recent"
fi
log_info 'Checking for Homebrew...'
if (( ! ${+commands[brew]} )) {
log_error 'No Homebrew command found. Please install Homebrew (https://brew.sh)'
return 2
}
brew bundle --file ${SCRIPT_HOME}/.Brewfile
rehash
log_group

View File

@ -0,0 +1,62 @@
autoload -Uz log_debug log_error log_info log_status log_group log_output
local -r _usage="Usage: %B${0}%b <source> <volume name> <output_name>
Create macOS disk image <volume name> <output_name> with contents of <source>"
if (( ! # )) {
log_error 'Called without arguments.'
log_output ${_usage}
return 2
}
local source=${1}
local volume_name=${2}
local output_name=${3}
log_group "Create macOS disk image"
local _hdiutil_flags
if (( _loglevel < 1 )) _hdiutil_flags='-quiet'
trap "hdiutil detach ${_hdiutil_flags} /Volumes/${output_name}; rm temp.dmg; log_group return 2" ERR
hdiutil create ${_hdiutil_flags} \
-volname "${volume_name}" \
-srcfolder ${source} \
-ov \
-fs APFS \
-format UDRW \
temp.dmg
hdiutil attach ${_hdiutil_flags} \
-noverify \
-readwrite \
-mountpoint /Volumes/${output_name} \
temp.dmg
log_info "Waiting 2 seconds to ensure mounted volume is available..."
sleep 2
log_status "Done"
log_info "Setting up disk volume..."
log_status "Volume icon"
SetFile -c icnC /Volumes/${output_name}/.VolumeIcon.icns
log_status "Icon positions"
osascript package.applescript ${output_name}
log_status "File permissions"
chmod -Rf go-w /Volumes/${output_name}
SetFile -a C /Volumes/${output_name}
rm -rf -- /Volumes/${output_name}/.fseventsd(N)
log_info "Converting disk image..."
hdiutil detach ${_hdiutil_flags} /Volumes/${output_name}
hdiutil convert ${_hdiutil_flags} \
-format ULMO \
-ov \
-o ${output_name}.dmg temp.dmg
rm temp.dmg
trap '' ERR
log_group
return 0

3
.github/scripts/utils.zsh/log_debug vendored Normal file
View File

@ -0,0 +1,3 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 2 )) print -PR -e "${CI:+::debug::}%F{220}DEBUG: ${@}%f"

3
.github/scripts/utils.zsh/log_error vendored Normal file
View File

@ -0,0 +1,3 @@
local icon=' ✖︎ '
print -u2 -PR "${CI:+::error::}%F{1} ${icon} %f ${@}"

16
.github/scripts/utils.zsh/log_group vendored Normal file
View File

@ -0,0 +1,16 @@
autoload -Uz log_info
if (( ! ${+_log_group} )) typeset -g _log_group=0
if (( ${+CI} )) {
if (( _log_group )) {
print "::endgroup::"
typeset -g _log_group=0
}
if (( # )) {
print "::group::${@}"
typeset -g _log_group=1
}
} else {
if (( # )) log_info ${@}
}

7
.github/scripts/utils.zsh/log_info vendored Normal file
View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "%F{4} ${(r:5:)icon}%f %B${@}%b"
}

7
.github/scripts/utils.zsh/log_output vendored Normal file
View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=''
print -PR " ${(r:5:)icon} ${@}"
}

7
.github/scripts/utils.zsh/log_status vendored Normal file
View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' >'
print -PR "%F{2} ${(r:5:)icon}%f ${@}"
}

7
.github/scripts/utils.zsh/log_warning vendored Normal file
View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "${CI:+::warning::}%F{3} ${(r:5:)icon} ${@}%f"
}

1
.github/scripts/utils.zsh/mkcd vendored Normal file
View File

@ -0,0 +1 @@
[[ -n ${1} ]] && mkdir -p ${1} && builtin cd ${1}

View File

@ -0,0 +1,9 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_IDENT} )) {
typeset -g CODESIGN_IDENT
log_info 'Setting up Apple Developer ID for application codesigning...'
read CODESIGN_IDENT'?Apple Developer Application ID: '
}
typeset -g CODESIGN_TEAM=$(print "${CODESIGN_IDENT}" | /usr/bin/sed -En 's/.+\((.+)\)/\1/p')

View File

@ -0,0 +1,24 @@
autoload -Uz read_codesign read_codesign_user log_info log_warning
if (( ! ${+CODESIGN_IDENT} )) {
read_codesign
}
if (( ! ${+CODESIGN_IDENT_USER} )) {
read_codesign_user
}
log_info 'Setting up password for notarization keychain...'
if (( ! ${+CODESIGN_IDENT_PASS} )) {
read -s CODESIGN_IDENT_PASS'?Apple Developer ID password: '
}
print ''
log_info 'Setting up notarization keychain...'
log_warning "
+ Your Apple ID and 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 'altool' only.
"
xcrun notarytool store-credentials 'OBS-Codesign-Password' --apple-id "${CODESIGN_IDENT_USER}" --team-id "${CODESIGN_TEAM}" --password "${CODESIGN_IDENT_PASS}"

View File

@ -0,0 +1,7 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_TEAM} )) {
typeset -g CODESIGN_TEAM
log_info 'Setting up Apple Developer Team ID for codesigning...'
read CODESIGN_TEAM'?Apple Developer Team ID (leave empty to use Apple Developer ID instead): '
}

View File

@ -0,0 +1,7 @@
autoload -Uz log_info
if (( ! ${+CODESIGN_IDENT_USER} )) {
typeset -g CODESIGN_IDENT_USER
log_info 'Setting up Apple ID for notarization...'
read CODESIGN_IDENT_USER'?Apple ID: '
}

View File

@ -0,0 +1,7 @@
if (( _loglevel > 1 )) {
xcodebuild ${@}
} else {
local -a xcbeautify_opts=()
if (( _loglevel == 0 )) xcbeautify_opts+=(--quiet)
xcodebuild ${@} 2>&1 | xcbeautify ${xcbeautify_opts}
}

17
.github/scripts/utils.zsh/set_loglevel vendored Normal file
View File

@ -0,0 +1,17 @@
autoload -Uz log_debug log_error log_output
local -r _usage="Usage: %B${0}%b <loglevel>
Set log level, following levels are supported: 0 (quiet), 1 (normal), 2 (verbose), 3 (debug)"
if (( ! # )); then
log_error 'Called without arguments.'
log_output ${_usage}
return 2
elif (( ${1} >= 4 )); then
log_error 'Called with loglevel > 3.'
log_output ${_usage}
fi
typeset -g -i -r _loglevel=${1}
log_debug "Log level set to '${1}'"

42
.github/scripts/utils.zsh/setup_ccache vendored Normal file
View File

@ -0,0 +1,42 @@
autoload -Uz log_debug log_warning log_error
if (( ! ${+project_root} )) {
log_error "'project_root' not set. Please set before running ${0}."
return 2
}
if (( ${+commands[ccache]} )) {
log_debug "Found ccache at ${commands[ccache]}"
typeset -gx CCACHE_CONFIGPATH="${project_root}/.ccache.conf"
ccache --set-config=run_second_cpp=true
ccache --set-config=direct_mode=true
ccache --set-config=inode_cache=true
ccache --set-config=compiler_check=content
ccache --set-config=file_clone=true
local -a sloppiness=(
include_file_mtime
include_file_ctime
file_stat_matches
system_headers
)
if [[ ${host_os} == macos ]] {
sloppiness+=(
modules
clang_index_store
)
ccache --set-config=sloppiness=${(j:,:)sloppiness}
}
if (( ${+CI} )) {
ccache --set-config=cache_dir="${GITHUB_WORKSPACE:-${HOME}}/.ccache"
ccache --set-config=max_size="${CCACHE_SIZE:-1G}"
ccache -z > /dev/null
}
} else {
log_warning "No ccache found on the system"
}

141
.gitignore vendored
View File

@ -1,108 +1,49 @@
#binaries
*.exe
*.dll
*.dylib
*.so
*.plugin
*.framework
*.systemextension
# Exclude everything
/*
#cmake
/build*/
!/build-aux/
/release*/
/debug*/
.vs/
*.o.d
*.ninja
.ninja*
.dirstamp
/cmake/.CMakeBuildNumber
.deps
CMakeUserPresets.json
# Except for default project files
!/.github
!/build-aux
!/cmake
!/deps
!/docs
!/libobs*
!/plugins
!/tests
!/UI
!.cirrus.xml
!.clang-format
!.cmake-format.json
!.editorconfig
!.git-blame-ignore-devs
!.gitmodules
!.gitignore
!.mailmap
!.swift-format
!AUTHORS
!buildspec.json
!CMakeLists.txt
!CMakePresets.json
!COC.rst
!COMMITMENT
!CONTRIBUTING.rst
!COPYING
!INSTALL
!README.rst
#xcode
*.xcodeproj/
/xcodebuild/
# Exclude lock files
*.lock.json
#clion
.idea/
cmake-build-debug/
#other stuff (windows stuff, qt moc stuff, etc)
Release_MD/
Release/
Debug/
x64/
ipch/
GeneratedFiles/
.moc/
/UI/obs.rc
.vscode/
/CI/include/*.lock.json
install_temp/
/other/
#make stuff
configure
depcomp
install-sh
Makefile.in
Makefile
#python
__pycache__
#sphinx
# Exclude files generated by Sphinx in-tree
/docs/sphinx/_build/*
!/docs/sphinx/_build/.gitignore
!/docs/sphinx/Makefile
#random useless file stuff
*.dmg
*.app
.directory
.hg
.depend
tags
*.trace
*.vsp
*.psess
*.swp
*.dat
*.clbin
*.log
*.tlog
*.sdf
*.opensdf
*.xml
*.ipch
*.css
*.xslt
*.aps
*.suo
*.ncb
*.user
*.lo
*.ilk
*.la
*.o
*.obj
*.pdb
*.res
*.dep
*.zip
*.lnk
*.chm
*~
.DS_Store
*/.DS_Store
*/**/.DS_Store
# Exclude modified Flatpak files
build-aux/flatpak-github-action-modified-*
#flatpak
/.flatpak-builder/
/_flatpak_build/
/flatpak_app/
/repo/
/CI/flatpak/flatpak-github-action-modified-*
# Exclude macOS legacy resource forks
.DS_Store
# Exclude CMake build number cache
/cmake/.CMakeBuildNumber

View File

@ -0,0 +1,3 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 2 )) print -PR -e -- "${CI:+::debug::}%F{220}DEBUG: ${@}%f"

View File

@ -0,0 +1,3 @@
local icon=' ✖︎ '
print -u2 -PR "${CI:+::error::}%F{1} ${icon} %f ${@}"

View File

@ -0,0 +1,16 @@
autoload -Uz log_info
if (( ! ${+_log_group} )) typeset -g _log_group=0
if (( ${+CI} )) {
if (( _log_group )) {
print "::endgroup::"
typeset -g _log_group=0
}
if (( # )) {
print "::group::${@}"
typeset -g _log_group=1
}
} else {
if (( # )) log_info ${@}
}

View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "%F{4} ${(r:5:)icon}%f %B${@}%b"
}

View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=''
print -PR " ${(r:5:)icon} ${@}"
}

View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' >'
print -PR "%F{2} ${(r:5:)icon}%f ${@}"
}

View File

@ -0,0 +1,7 @@
if (( ! ${+_loglevel} )) typeset -g _loglevel=1
if (( _loglevel > 0 )) {
local icon=' =>'
print -PR "${CI:+::warning::}%F{3} ${(r:5:)icon} ${@}%f"
}

View File

@ -0,0 +1,17 @@
autoload -Uz log_debug log_error
local -r _usage="Usage: %B${0}%b <loglevel>
Set log level, following levels are supported: 0 (quiet), 1 (normal), 2 (verbose), 3 (debug)"
if (( ! # )); then
log_error 'Called without arguments.'
log_output ${_usage}
return 2
elif (( ${1} >= 4 )); then
log_error 'Called with loglevel > 3.'
log_output ${_usage}
fi
typeset -g -i -r _loglevel=${1}
log_debug "Log level set to '${1}'"

190
build-aux/.run-format.zsh Executable file
View File

@ -0,0 +1,190 @@
#!/usr/bin/env zsh
builtin emulate -L zsh
setopt EXTENDED_GLOB
setopt PUSHD_SILENT
setopt ERR_EXIT
setopt ERR_RETURN
setopt NO_UNSET
setopt PIPE_FAIL
setopt NO_AUTO_PUSHD
setopt NO_PUSHD_IGNORE_DUPS
setopt FUNCTION_ARGZERO
## Enable for script debugging
# setopt WARN_CREATE_GLOBAL
# setopt WARN_NESTED_VAR
# setopt XTRACE
autoload -Uz is-at-least && if ! is-at-least 5.2; then
print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade zsh to fix this issue."
exit 1
fi
invoke_formatter() {
if (( # < 1 )) {
log_error "Usage invoke_formatter [formatter_name]"
exit 2
}
case ${1} {
clang)
if (( ${+commands[clang-format-13]} )) {
local formatter=clang-format-13
} elif (( ${+commands[clang-format]} )) {
local formatter=clang-format
} else {
log_error "No viable clang-format version found (required 13.0.1)"
exit 2
}
local -a formatter_version=($(${formatter} --version))
if ! is-at-least 13.0.1 ${formatter_version[-1]}; then
log_error "clang-format is not version 13.0.1 or above (found ${formatter_version[-1]}."
exit 2
fi
if ! is-at-least ${formatter_version[-1]} 13.0.1; then
log_error "clang-format is more recent than version 13.0.1 (found ${formatter_version[-1]})."
exit 2
fi
local -a source_files=((libobs|libobs-*|UI|plugins)/**/*.(c|cpp|h|hpp|m|mm)(.N))
source_files=(${source_files:#*/(obs-websocket/deps|decklink/*/decklink-sdk|enc-amf|mac-syphon/syphon-framework|obs-outputs/ftl-sdk)/*})
local -a format_args=(-style=file -fallback-style=none)
if (( _loglevel > 2 )) format_args+=(--verbose)
;;
cmake)
local formatter=cmake-format
if (( ${+commands[cmake-format]} )) {
local cmake_format_version=$(cmake-format --version)
if ! is-at-least 0.6.13 ${cmake_format_version}; then
log_error "cmake-format is not version 0.6.13 or above (found ${cmake_format_version})."
exit 2
fi
} else {
log_error "No viable cmake-format version found (required 0.6.13)"
exit 2
}
local -a source_files=((libobs|libobs-*|UI|plugins|cmake)/**/(CMakeLists.txt|*.cmake)(.N))
source_files=(${source_files:#*/(obs-outputs/ftl-sdk|jansson|decklink/*/decklink-sdk|enc-amf|obs-websocket|obs-browser|win-dshow/libdshowcapture)/*})
local -a format_args=()
if (( _loglevel > 2 )) format_args+=(--log-level debug)
;;
swift)
local formatter=swift-format
if (( ${+commands[swift-format]} )) {
local swift_format_version=$(swift-format --version)
if ! is-at-least 508.0.0 ${swift_format_version}; then
log_error "swift-format is not version 508.0.0 or above (found ${swift_format_version})."
exit 2
fi
} else {
log_error "No viable swift-format version found (required 508.0.0)"
exit 2
}
local -a source_files=((libobs|libobs-*|UI|plugins)/**/*.swift(.N))
local -a format_args=()
;;
*) log_error "Invalid formatter specified: ${1}. Valid options are clang-format, cmake-format, and swift-format."; exit 2 ;;
}
local file
local -i num_failures=0
if (( check_only )) {
for file (${source_files}) {
if (( _loglevel > 1 )) log_info "Checking format of ${file}..."
if ! "${formatter}" ${format_args} "${file}" | diff -q "${file}" - &> /dev/null; then
log_error "${file} requires formatting changes."
if (( fail_on_error == 2 )) return 2;
num_failures=$(( num_failures + 1 ))
else
if (( _loglevel > 1 )) log_status "${file} requires no formatting changes."
fi
}
if (( fail_on_error && num_failures )) return 2;
} elif (( ${#source_files} )) {
format_args+=(-i)
"${formatter}" ${format_args} ${source_files}
}
}
run_format() {
if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
if (( ! ${+FORMATTER_NAME} )) typeset -g FORMATTER_NAME=${${(s:-:)ZSH_ARGZERO:t:r}[2]}
typeset -g host_os=${${(L)$(uname -s)}//darwin/macos}
local -i fail_on_error=0
local -i check_only=0
local -i verbosity=1
local -r _version='1.0.0'
fpath=("${SCRIPT_HOME}/.functions" ${fpath})
autoload -Uz set_loglevel log_info log_error log_output log_status log_warning
local -r _usage="
Usage: %B${functrace[1]%:*}%b <option>
%BOptions%b:
%F{yellow} Formatting options%f
-----------------------------------------------------------------------------
%B-c | --check%b Check only, no actual formatting takes place
%F{yellow} Output options%f
-----------------------------------------------------------------------------
%B-v | --verbose%b Verbose (more detailed output)
%B--fail-[never|error] Fail script never/on formatting change - default: %B%F{green}never%f%b
%B--debug%b Debug (very detailed and added output)
%F{yellow} General options%f
-----------------------------------------------------------------------------
%B-h | --help%b Print this usage help
%B-V | --version%b Print script version information"
local -a args
while (( # )) {
case ${1} {
--)
shift
args+=($@)
break
;;
-c|--check) check_only=1; shift ;;
-v|--verbose) (( verbosity += 1 )); shift ;;
-h|--help) log_output ${_usage}; exit 0 ;;
-V|--version) print -Pr "${_version}"; exit 0 ;;
--debug) verbosity=3; shift ;;
--fail-never)
fail_on_error=0
shift
;;
--fail-error)
fail_on_error=1
shift
;;
--fail-fast)
fail_on_error=2
shift
;;
*) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
}
}
set -- ${(@)args}
set_loglevel ${verbosity}
invoke_formatter ${FORMATTER_NAME}
}
run_format ${@}

1
build-aux/run-clang-format Symbolic link
View File

@ -0,0 +1 @@
.run-format.zsh

1
build-aux/run-cmake-format Symbolic link
View File

@ -0,0 +1 @@
.run-format.zsh

1
build-aux/run-swift-format Symbolic link
View File

@ -0,0 +1 @@
.run-format.zsh