Przeglądaj źródła

CI: Add new build and packaging scripts for Linux

PatTheMav 2 lat temu
rodzic
commit
ae897c2764

+ 7 - 0
.github/scripts/.Aptfile

@@ -0,0 +1,7 @@
+package 'ccache'
+package 'cmake'
+package 'curl'
+package 'git'
+package 'jq'
+package 'ninja-build', bin: 'ninja'
+package 'pkg-config'

+ 28 - 0
.github/scripts/.build.zsh

@@ -63,6 +63,7 @@ build() {
   local -r -a _valid_targets=(
     macos-x86_64
     macos-arm64
+    linux-x86_64
   )
   local target
   local config='RelWithDebInfo'
@@ -230,6 +231,33 @@ ${_usage_host:-}"
           -DOBS_CODESIGN_IDENTITY:STRING=${CODESIGN_IDENT:--}
         )
         ;;
+      linux-*)
+        cmake_args+=(
+          -S ${PWD} -B "build_${target##*-}"
+          -G "${generator}"
+          -DCMAKE_BUILD_TYPE:STRING=${config}
+          -DCEF_ROOT_DIR:PATH="${project_root}/.deps/cef_binary_${CEF_VERSION}_${target//-/_}"
+        )
+
+        local cmake_version
+        read -r _ _ cmake_version <<< "$(cmake --version)"
+
+        cmake_build_args+=("build_${target##*-}" --config ${config})
+
+        if [[ ${generator} == 'Unix Makefiles' ]] {
+          cmake_build_args+=(--parallel $(( $(nproc) + 1 )))
+        } else {
+          cmake_build_args+=(--parallel)
+        }
+
+        cmake_args+=(
+          -DENABLE_AJA:BOOL=OFF
+          -DENABLE_WEBRTC:BOOL=OFF
+        )
+        if (( ! UBUNTU_2210_OR_LATER )) cmake_args+=(-DENABLE_NEW_MPEGTS_OUTPUT:BOOL=OFF)
+
+        cmake_install_args+=(build_${target##*-} --prefix ${project_root}/build_${target##*-}/install/${config})
+        ;;
     }
 
     if (( _print_config )) { log_output "CMake configuration: ${cmake_args}"; exit 0 }

+ 30 - 0
.github/scripts/.package.zsh

@@ -260,6 +260,36 @@ ${_usage_host:-}"
     }
 
     log_group
+
+  } elif [[ ${host_os} == linux ]] {
+    local -a cmake_args=()
+    if (( _loglevel > 1 )) cmake_args+=(--verbose)
+
+    if (( package )) {
+      log_group "Packaging obs-studio..."
+      pushd ${project_root}
+      cmake --build build_${target##*-} --config ${config} -t package ${cmake_args}
+      output_name="${output_name}-${target##*-}-linux-gnu"
+
+      pushd ${project_root}/build_${target##*-}
+      local -a files=(obs-studio-*-Linux*.(ddeb|deb))
+      for file (${files}) {
+        mv ${file} ${file//obs-studio-*-Linux/${output_name}}
+      }
+      popd
+      popd
+    } else {
+      log_group "Archiving obs-studio..."
+      output_name="${output_name}-${target##*-}-linux-gnu"
+
+      local _tarflags='cJf'
+      if (( _loglevel > 1 || ${+CI} )) _tarflags="v${_tarflags}"
+
+      pushd ${project_root}/build_${target##*-}/install/${config}
+      XZ_OPT=-T0 tar "-${_tarflags}" ${project_root}/build_${target##*-}/${output_name}.tar.xz (bin|lib|share)
+      popd
+    }
+    log_group
   }
 }
 

+ 1 - 0
.github/scripts/build-linux

@@ -0,0 +1 @@
+./.build.zsh

+ 1 - 0
.github/scripts/package-linux

@@ -0,0 +1 @@
+./.package.zsh

+ 61 - 0
.github/scripts/utils.zsh/check_linux

@@ -0,0 +1,61 @@
+autoload -Uz log_info log_status log_error log_debug log_warning log_group
+
+log_group 'Check Linux build requirements'
+log_debug 'Checking Linux distribution name and version...'
+
+# Check for Ubuntu version 22.10 or later, which have srt and librist available via apt-get
+typeset -g -i UBUNTU_2210_OR_LATER=0
+if [[ -f /etc/os_release ]] {
+  local dist_name
+  local dist_version
+  read -r dist_name dist_version <<< "$(source /etc/os_release; print "${NAME} ${VERSION_ID}")"
+
+  autoload -Uz is-at-least
+  if [[ ${dist_name} == Ubuntu ]] && is-at-least 22.10 ${dist_version}; then
+    typeset -g -i UBUNTU_2210_OR_LATER=1
+  fi
+}
+
+log_debug 'Checking for apt-get...'
+if (( ! ${+commands[apt-get]} )) {
+  log_error 'No apt-get command found. Please install apt'
+  return 2
+} else {
+  log_debug "Apt-get located at ${commands[apt-get]}"
+}
+
+local -a dependencies=("${(fA)$(<${SCRIPT_HOME}/.Aptfile)}")
+local -a install_list
+local binary
+
+sudo apt-get update -qq
+
+for dependency (${dependencies}) {
+  local -a tokens=(${=dependency//(,|:|\')/})
+
+  if [[ ! ${tokens[1]} == package ]] continue
+
+  if [[ ${#tokens} -gt 2 && ${tokens[3]} == bin ]] {
+    binary=${tokens[4]}
+  } else {
+    binary=${tokens[2]}
+  }
+
+  if (( ! ${+commands[${binary}]} )) install_list+=(${tokens[2]})
+}
+
+log_debug "List of dependencies to install: ${install_list}"
+if (( #install_list )) {
+  if (( ! ${+CI} )) log_warning 'Dependency installation via apt may require elevated privileges'
+
+  local -a apt_args=(
+    ${CI:+-y}
+    --no-install-recommends
+  )
+  if (( _loglevel == 0 )) apt_args+=(--quiet)
+
+  sudo apt-get ${apt_args} install ${install_list}
+}
+
+rehash
+log_group

+ 187 - 0
.github/scripts/utils.zsh/setup_linux

@@ -0,0 +1,187 @@
+autoload -Uz log_group log_error log_status log_info log_debug
+
+if (( ! ${+commands[curl]} )) {
+  log_error 'curl not found. Please install curl.'
+  return 2
+}
+
+if (( ! ${+commands[jq]} )) {
+  log_error 'jq not found. Please install jq.'
+  return 2
+}
+
+if (( ! ${+project_root} )) {
+  log_error "'project_root' not set. Please set before running ${0}."
+  return 2
+}
+
+if (( ! ${+target} )) {
+  log_error "'target' not set. Please set before running ${0}."
+  return 2
+}
+
+local -a curl_opts=()
+if (( ! ${+CI} )) {
+  curl_opts+=(--progress-bar --continue-at -)
+} else {
+  curl_opts+=(--show-error --silent)
+}
+curl_opts+=(--location -O ${@})
+
+pushd ${project_root}
+
+typeset -g QT_VERSION
+read -r QT_VERSION <<< \
+  "$(jq -r --arg target "${target}" \
+    '.platformConfig[$target] | { qtVersion } | join(" ")' \
+    ${buildspec_file})"
+
+if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
+  log_group 'Installing obs-studio build dependencies...'
+
+  mkdir -p ${project_root}/.deps
+  local deps_version
+  local deps_baseurl
+  local deps_label
+  local deps_hash
+
+  IFS=';' read -r deps_version deps_baseurl deps_label deps_hash <<< \
+    "$(jq -r --arg target "${target}" \
+      '.dependencies["cef"] | {version, baseUrl, "label", "hash": .hashes[$target]} | join(";")' \
+      ${buildspec_file})"
+
+  if (( ! deps_version )) {
+    log_error 'No valid cef spec found in buildspec.json.'
+    return 2
+  }
+  log_group 'Setting up pre-built Chromium Embedded Framework...'
+
+  pushd ${project_root}/.deps
+  local _filename="cef_binary_${deps_version}_${target//-/_}.tar.xz"
+  local _url=${deps_baseurl}/${_filename}
+  local _target="cef_binary_${deps_version}_${target//-/_}"
+  typeset -g CEF_VERSION=${deps_version}
+
+  log_status 'Checking for available wrapper library...'
+  local -i _skip=0
+  if [[ -f ${_target}/build/libcef_dll_wrapper/libcef_dll_wrapper.a ]] {
+    _skip=1
+  }
+
+  if ! (( _skip )) {
+    if [[ ! -f ${_filename} ]] {
+      log_debug "Running curl ${curl_opts} ${_url}"
+      curl ${curl_opts} ${_url} && \
+        log_status "Downloaded ${deps_label} for ${target}."
+    } else {
+      log_status "Found downloaded ${deps_label}"
+    }
+
+    read -r artifact_checksum _ <<< "$(sha256sum ${_filename})"
+    if [[ ${deps_hash} != ${artifact_checksum} ]] {
+      log_error "Checksum of downloaded ${deps_label} does not match specification.
+  Expected : ${deps_hash}
+  Actual   : ${artifact_checksum}"
+      return 2
+    }
+    log_status "Checksum of downloaded ${deps_label} matches."
+    mkdir -p ${_target} && pushd ${_target}
+
+    XZ_OPT=-T0 tar --strip-components 1 -xJf ../${_filename} && log_status "${deps_label} extracted."
+
+    if [[ ! -f build/libcef_dll_wrapper/libcef_dll_wrapper.a ]] {
+      log_group "Configuring CEF wrapper library..."
+
+      local -a cmake_args=(
+        -DPROJECT_ARCH:STRING=${target##*-}
+        -DCEF_COMPILER_FLAGS:STRING="-Wno-deprecated-copy"
+        -DCMAKE_BUILD_TYPE:STRING=${config}
+        -DCMAKE_CXX_FLAGS:STRING="-std=c++11 -Wno-deprecated-declarations -Wno-unknonw-warning-option"
+        -DCMAKE_EXE_LINKER_FLAGS:STRING="-std=c++11"
+      )
+      if (( _loglevel == 0 )) cmake_args+=(-Wno-deprecated -Wno-dev --log-level=ERROR)
+      if (( ${+commands[ccache]} )) {
+        cmake_args+=(
+          -DCMAKE_C_COMPILER_LAUNCHER:STRING=ccache
+          -DCMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache
+        )
+      }
+
+      cmake -S . -B build -G Ninja ${cmake_args}
+
+      log_group "Building CEF Wrapper library..."
+      cmake --build build
+    }
+
+    mkdir -p build/libcef_dll
+    popd
+  } else {
+    log_info 'Found existing Chromium Embedded Framework and loader library...'
+  }
+  popd
+
+  local -a apt_args=(
+    ${CI:+-y}
+    --no-install-recommends
+  )
+  if (( _loglevel == 0 )) apt_args+=(--quiet)
+
+  local suffix
+  if [[ ${CPUTYPE} != ${target##*-} ]] {
+    local -A arch_mappings=(
+      aarch64 arm64
+      x86_64 amd64
+    )
+
+    suffix=":${arch_mappings[${target##*-}]}"
+    sudo apt-get install ${apt_args} gcc-${${target##*-}//_/-}-linux-gnu g++-${${target##*-}//_/-}-linux-gnu
+  }
+
+  sudo apt-get install ${apt_args} \
+    build-essential \
+    libcurl4-openssl-dev \
+    libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev \
+    libswresample-dev libswscale-dev \
+    libjansson-dev \
+    libx11-xcb-dev \
+    libgles2-mesa-dev libgles2-mesa \
+    libwayland-dev \
+    libpipewire-0.3-dev \
+    libpulse-dev \
+    libx264-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 libxss-dev libglvnd-dev \
+    libxkbcommon-dev \
+    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 \
+    libpci-dev libdrm-dev \
+    nlohmann-json3-dev libwebsocketpp-dev libasio-dev libvpl-dev libqrcodegencpp-dev
+
+  if (( UBUNTU_2210_OR_LATER )) sudo apt-get install ${apt_args} librist-dev libsrt-openssl-dev
+
+  local -a _qt_packages=()
+
+  if (( QT_VERSION == 6 )) {
+    _qt_packages+=(
+      qt6-base-dev
+      libqt6svg6-dev
+      qt6-base-private-dev
+    )
+  } else {
+    log_error "Unsupported Qt version '${QT_VERSION}' specified."
+    return 2
+  }
+
+  sudo apt-get install ${apt_args} ${_qt_packages}
+} else {
+  local cef_version
+  read -r cef_version <<< \
+    "$(jq -r '.dependencies | [.cef.version] | join(" ")' ${buildspec_file})"
+
+  typeset -g CEF_VERSION=${cef_version}
+}