Skip to content

Instantly share code, notes, and snippets.

@aleitner
Last active February 6, 2024 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aleitner/fe4c8668049b07f32ea2b2782f6c0d4a to your computer and use it in GitHub Desktop.
Save aleitner/fe4c8668049b07f32ea2b2782f6c0d4a to your computer and use it in GitHub Desktop.
Build cef
#!/usr/bin/env bash
set -euo pipefail
usage() {
echo "Usage: $0 [options]"
echo "Options:"
echo " --manual-build Run the build process manually without automatic tools."
echo " --x64-build Perform an x64 build (default)."
echo " --arm64-build Perform an ARM64 cross-compile build."
echo " --no-build Skip the build and update CEF from a predefined URL."
echo " --patches-dir <dir> Specify the directory containing patch files to apply (only with --manual-build)."
echo " -h, --help Show this message."
exit 1
}
# Initialize default values
MANUAL_BUILD=false
BUILD_FLAG="--x64-build" # Set the default build flag to x64
OUT_DIR="out/Release_GN_x64" # Set the default output dir to x64
PATCHES_DIR=""
NO_BUILD=false
CEF_VERSION="119.4.7+g55e15c8+chromium-119.0.6045.199"
CEF_URL="https://cef-builds.spotifycdn.com/cef_binary_${CEF_VERSION}_linux64.tar.bz2" # Define the URL where the CEF should be downloaded from
CEF_COMMIT_HASH=$(echo $CEF_VERSION | cut -d '+' -f 2 | cut -c 2-)
# Process command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--no-build)
NO_BUILD=true
shift
;;
--manual-build)
MANUAL_BUILD=true
shift
;;
--x64-build)
BUILD_FLAG="--x64-build"
OUT_DIR="out/Release_GN_x64"
shift
;;
--arm64-build)
BUILD_FLAG="--arm64-build"
OUT_DIR="out/Release_GN_arm64"
shift
;;
--patches-dir)
PATCHES_DIR="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown argument: $1"
usage
;;
esac
done
# Check if we are in an x64 environment for non-cross-compile builds
ARCH=$(uname -m)
if [[ "${BUILD_FLAG}" == "--x64-build" && "${ARCH}" != "x86_64" ]]; then
echo "The default x64 build can only be run in an x64 environment."
exit 1
fi
# Define the build directory and ensure it exists.
BUILD_DIR="${HOME}/code"
AUTOMATE_DIR="${BUILD_DIR}/automate"
CHROMIUM_DIR="${BUILD_DIR}/chromium_git"
CEF_DIR="${CHROMIUM_DIR}/chromium/src/cef"
CEF_INSTALL_DIR="/opt/cef"
# Ensure the build and automate directories exist.
mkdir -p "${BUILD_DIR}"
mkdir -p "${AUTOMATE_DIR}"
# Function to apply patch files from PATCHES_DIR to CEF_DIR
apply_patches() {
if [ -z "${PATCHES_DIR}" ]; then
echo "No patches directory specified, skipping patch application."
return 0
fi
if [ ! -d "${PATCHES_DIR}" ]; then
echo "The specified patches directory does not exist: ${PATCHES_DIR}"
exit 1
fi
echo "Applying patches from ${PATCHES_DIR} to ${CEF_DIR}..."
# First, copy the directory structure and files over
cp -rv "${PATCHES_DIR}"/*/ "${CEF_DIR}/"
# Then, apply each patch file
local patch_file
for patch_file in "${PATCHES_DIR}"/*.patch; do
if [ -f "$patch_file" ]; then
# Ensure we are in the correct directory when applying patches
(cd "${CEF_DIR}" && git apply "$patch_file") || {
echo "Failed to apply patch: $patch_file"
exit 1
}
fi
done
}
# copy CEF to installation directory
copy_distribution_to_opt() {
local src_dir="$1"
sudo rm -rf "${CEF_INSTALL_DIR:?}/"*
sudo mkdir -p "${CEF_INSTALL_DIR}"
sudo cp -r "${src_dir}"/* "${CEF_INSTALL_DIR}/"
pushd "${CEF_INSTALL_DIR}"
for file in Resources/*; do
sudo ln -s "../${file}" Release/
done
popd
}
no_build() {
local temp_file="/tmp/cef.tar.bz2"
local temp_extract_dir="/tmp/cef_extract"
echo "Downloading from URL: $CEF_URL..."
if ! curl -L -o "$temp_file" "$CEF_URL"; then
echo "Download failed!"
exit 1
fi
echo 'Creating temporary extraction directory...'
if ! mkdir -p "$temp_extract_dir"; then
echo "Failed to create temporary extraction directory: $temp_extract_dir"
rm -f "$temp_file"
exit 1
fi
echo 'Extracting file...'
if ! tar -xjf "$temp_file" --strip-components=1 -C "$temp_extract_dir"; then
echo "Failed to extract files to $temp_extract_dir"
rm -f "$temp_file"
exit 1
fi
echo 'Removing downloaded tarball...'
rm -f "$temp_file"
# Use copy_distribution_to_opt to copy files to their destination
copy_distribution_to_opt "$temp_extract_dir"
# Cleaning up temporary extraction directory
rm -rf "$temp_extract_dir"
}
# Function to run the build command
run_build() {
echo "Running the automate build script..."
python3 "${AUTOMATE_SCRIPT}" \
--download-dir="${CHROMIUM_DIR}" \
--checkout="${CEF_COMMIT_HASH}" \
--minimal-distrib \
--force-clean \
--force-clean-deps \
--no-debug-build \
--no-distrib-docs \
--no-distrib-archive \
--build-target="cefclient chrome_sandbox"\
--distrib-subdir=libcef \
${BUILD_FLAG}
copy_distribution_to_opt "${CEF_DIR}/binary_distrib/libcef"
}
# Function to run the script to build manually
run_manual_build() {
echo "Running the automate script without building..."
python3 "${AUTOMATE_SCRIPT}" \
--download-dir="${CHROMIUM_DIR}" \
--checkout="${CEF_COMMIT_HASH}" \
--no-distrib \
--no-build \
--force-clean \
--force-clean-deps
# Apply any patches if specified
apply_patches
# Update PATH
export PATH="${CHROMIUM_DIR}/depot_tools:$PATH"
# Navigate to the CEF directory and create CEF projects
cd "${CEF_DIR}"
./cef_create_projects.sh
# Navigate to the src directory and build cefsimple
cd "${CHROMIUM_DIR}/chromium/src"
autoninja -C "${OUT_DIR}" cefsimple chrome_sandbox
# Create a CEF binary distribution
cd "${CEF_DIR}/tools"
./make_distrib.sh --ninja-build --no-symbols --no-docs --no-archive --minimal --distrib-subdir=libcef ${BUILD_FLAG}
# Copy distribution to /opt/cef
copy_distribution_to_opt "${CHROMIUM_DIR}/chromium/src/cef/binary_distrib/libcef_minimal"
}
# is_debug: Indicates whether to perform a debug build. Set to false for a release build.
# chrome_pgo_phase: Controls Profile-Guided Optimization. Set to 0 to disable.
# use_sysroot: Determines whether the build uses the Chromium-provided sysroot or locally installed packages. Usually set to true to use Chromium's sysroot. Must be set to false if the build target is cefclient
# symbol_level: Sets the level of debug symbols. 1 is the minimum level for backtrace symbols.
# is_cfi: Enables or disables Control Flow Integrity checks. Set to false to disable.
# use_thin_lto: Enables or disables Thin Link Time Optimization. Set to false to disable.
# use_vaapi: Determines whether to use the Video Acceleration API. Set to false to disable when building for headless environments.
# use_allocator: Specifies which memory allocator to use. 'none' defers to the system's C library allocator.
# ozone_platform_headless: Enables the headless Ozone platform which doesn't require display server dependencies. Set to true for headless builds.
export GN_DEFINES="is_official_build=true \
is_debug=false \
chrome_pgo_phase=0 \
use_sysroot=true \
symbol_level=1 \
is_cfi=false \
use_thin_lto=false \
use_vaapi=false \
use_allocator=none \
use_ozone=true \
ozone_auto_platforms=false \
ozone_platform_headless=true \
ozone_platform_x11=false \
ozone_platform_wayland=false \
ozone_platform_drm=false"
# Detect OS distribution and architecture
OS_ID=""
if command -v lsb_release >/dev/null; then
OS_ID=$(lsb_release -si)
elif [ -f "/etc/os-release" ]; then
OS_ID=$(grep ^ID= /etc/os-release | cut -d'=' -f 2)
else
echo "Unable to detect OS distribution. Exiting..."
exit 1
fi
# Install Ubuntu build dependencies using provided script.
DEPS_SCRIPT="${BUILD_DIR}/install-build-deps.py"
if [[ "$OS_ID" == "Ubuntu" ]] && [ ! -f "${DEPS_SCRIPT}" ]; then
echo "Installing build dependencies..."
curl 'https://chromium.googlesource.com/chromium/src/+/main/build/install-build-deps.py?format=TEXT' | base64 -d > "${DEPS_SCRIPT}"
sudo python3 "${DEPS_SCRIPT}" --no-arm --no-chromeos-fonts --no-nacl
fi
# Common build dependencies with Python packages
sudo python3 -m pip install dataclasses importlib_metadata
# Download the automate-git.py script into the automate directory if it doesn't exist.
AUTOMATE_SCRIPT="${AUTOMATE_DIR}/automate-git.py"
AUTOMATE_SCRIPT_URL="https://raw.githubusercontent.com/chromiumembedded/cef/${CEF_COMMIT_HASH}/tools/automate/automate-git.py"
if [ ! -f "${AUTOMATE_SCRIPT}" ]; then
echo "Downloading the automate-git.py script..."
curl "${AUTOMATE_SCRIPT_URL}" -o "${AUTOMATE_SCRIPT}"
fi
# Run the appropriate function based on the --no-build option
if [ "$NO_BUILD" = true ]; then
no_build
elif [ "$MANUAL_BUILD" = true ]; then
run_manual_build
else
run_build
fi
echo "Build process completed successfully"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment