mirror of
https://github.com/ValveSoftware/Proton.git
synced 2024-12-27 07:05:46 +03:00
76406455ac
We can move everything but Liberation fonts build to the container. Sadly those require newer version of fontforge than the one available in the Steam RT. There's some extra logic necessary to assure that font build triggers in the container with the default/all targets. This removes the requirement to have afdko and fonttools installed on the host.
324 lines
9.8 KiB
Bash
Executable File
324 lines
9.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -eu
|
|
|
|
SRCDIR="$(dirname "$0")"
|
|
DEFAULT_BUILD_NAME="proton-localbuild" # If no --build-name specified
|
|
|
|
# Output helpers
|
|
COLOR_ERR=""
|
|
COLOR_STAT=""
|
|
COLOR_INFO=""
|
|
COLOR_CMD=""
|
|
COLOR_CLEAR=""
|
|
if [[ $(tput colors 2>/dev/null || echo 0) -gt 0 ]]; then
|
|
COLOR_ERR=$'\e[31;1m'
|
|
COLOR_STAT=$'\e[32;1m'
|
|
COLOR_INFO=$'\e[30;1m'
|
|
COLOR_CMD=$'\e[93;1m'
|
|
COLOR_CLEAR=$'\e[0m'
|
|
fi
|
|
|
|
sh_quote() {
|
|
local quoted
|
|
quoted="$(printf '%q ' "$@")"; [[ $# -eq 0 ]] || echo "${quoted:0:-1}";
|
|
}
|
|
err() { echo >&2 "${COLOR_ERR}!!${COLOR_CLEAR} $*"; }
|
|
stat() { echo >&2 "${COLOR_STAT}::${COLOR_CLEAR} $*"; }
|
|
info() { echo >&2 "${COLOR_INFO}::${COLOR_CLEAR} $*"; }
|
|
showcmd() { echo >&2 "+ ${COLOR_CMD}$(sh_quote "$@")${COLOR_CLEAR}"; }
|
|
die() { err "$@"; exit 1; }
|
|
finish() { stat "$@"; exit 0; }
|
|
cmd() { showcmd "$@"; "$@"; }
|
|
|
|
#
|
|
# Dependency Checks
|
|
#
|
|
|
|
MISSING_DEPENDENCIES=0
|
|
|
|
dependency_command() {
|
|
local COMMAND=$1
|
|
shift
|
|
if ! command -v "$COMMAND" &> /dev/null; then
|
|
err "Couldn't find command '$COMMAND'. Please install ${@:-$COMMAND}."
|
|
MISSING_DEPENDENCIES=1
|
|
fi
|
|
}
|
|
|
|
CONTAINER_MOUNT_OPTS=""
|
|
|
|
check_container_engine() {
|
|
stat "Trying $1."
|
|
if ! cmd $1 run --rm $arg_protonsdk_image; then
|
|
info "$1 is unable to run the container."
|
|
return 1
|
|
fi
|
|
|
|
touch permission_check
|
|
local inner_uid="$($1 run -v "$(pwd):/test$CONTAINER_MOUNT_OPTS" \
|
|
--rm $arg_protonsdk_image \
|
|
stat --format "%u" /test/permission_check 2>&1)"
|
|
rm permission_check
|
|
|
|
if [[ $inner_uid == *"Permission denied"* ]]; then
|
|
err "The container cannot access files. Are you using SELinux?"
|
|
die "Please read README.md and check your $1 setup works."
|
|
elif [ "$inner_uid" -eq 0 ]; then
|
|
# namespace maps the user as root or the build is performed as host's root
|
|
ROOTLESS_CONTAINER=1
|
|
elif [ "$inner_uid" -eq "$(id -u)" ]; then
|
|
ROOTLESS_CONTAINER=0
|
|
else
|
|
err "File owner's UID doesn't map to 0 or $(id -u) in the container."
|
|
die "Don't know how to map permissions. Please check your $1 setup."
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Configure
|
|
#
|
|
|
|
THIS_COMMAND="$0 $*" # For printing, not evaling
|
|
MAKEFILE="./Makefile"
|
|
|
|
# This is not rigorous. Do not use this for untrusted input. Do not. If you need a version of
|
|
# this for untrusted input, rethink the path that got you here.
|
|
function escape_for_make() {
|
|
local escape="$1"
|
|
escape="${escape//\\/\\\\}" # '\' -> '\\'
|
|
escape="${escape//#/\\#}" # '#' -> '\#'
|
|
escape="${escape//\$/\$\$}" # '$' -> '$$'
|
|
escape="${escape// /\\ }" # ' ' -> '\ '
|
|
echo "$escape"
|
|
}
|
|
|
|
function configure() {
|
|
local steamrt_image="$1"
|
|
local steamrt_name="$2"
|
|
local srcdir
|
|
srcdir="$(dirname "$0")"
|
|
|
|
# Build name
|
|
local build_name="$arg_build_name"
|
|
if [[ -n $build_name ]]; then
|
|
info "Configuring with build name: $build_name"
|
|
else
|
|
build_name="$DEFAULT_BUILD_NAME"
|
|
info "No build name specified, using default: $build_name"
|
|
fi
|
|
|
|
dependency_command fontforge
|
|
dependency_command find "findutils"
|
|
dependency_command make "GNU Make"
|
|
dependency_command rsync
|
|
dependency_command wget
|
|
dependency_command xz
|
|
dependency_command patch
|
|
dependency_command git
|
|
dependency_command python3
|
|
|
|
if [ "$MISSING_DEPENDENCIES" -ne 0 ]; then
|
|
die "Missing dependencies, cannot continue."
|
|
fi
|
|
|
|
if [[ -n "$arg_relabel_volumes" ]]; then
|
|
CONTAINER_MOUNT_OPTS=:Z
|
|
fi
|
|
|
|
if [[ -n "$arg_container_engine" ]]; then
|
|
check_container_engine "$arg_container_engine" || die "Specified container engine \"$arg_container_engine\" doesn't work"
|
|
else
|
|
stat "Trying to find usable container engine."
|
|
if check_container_engine docker; then
|
|
arg_container_engine="docker"
|
|
elif check_container_engine podman; then
|
|
arg_container_engine="podman"
|
|
else
|
|
die "${arg_container_engine:-Container engine discovery} has failed. Please fix your setup."
|
|
fi
|
|
fi
|
|
|
|
stat "Using $arg_container_engine."
|
|
|
|
## Write out config
|
|
# Don't die after this point or we'll have rather unhelpfully deleted the Makefile
|
|
[[ ! -e "$MAKEFILE" ]] || rm "$MAKEFILE"
|
|
|
|
{
|
|
# Config
|
|
echo "# Generated by: $THIS_COMMAND"
|
|
echo ""
|
|
echo "SRCDIR := $(escape_for_make "$srcdir")"
|
|
echo "BUILD_NAME := $(escape_for_make "$build_name")"
|
|
|
|
# SteamRT
|
|
echo "STEAMRT_NAME := $(escape_for_make "$steamrt_name")"
|
|
echo "STEAMRT_IMAGE := $(escape_for_make "$steamrt_image")"
|
|
|
|
echo "ROOTLESS_CONTAINER := $ROOTLESS_CONTAINER"
|
|
echo "CONTAINER_ENGINE := $arg_container_engine"
|
|
if [[ -n "$arg_docker_opts" ]]; then
|
|
echo "DOCKER_OPTS := $arg_docker_opts"
|
|
fi
|
|
if [[ -n "$CONTAINER_MOUNT_OPTS" ]]; then
|
|
echo "CONTAINER_MOUNT_OPTS := $CONTAINER_MOUNT_OPTS"
|
|
fi
|
|
if [[ -n "$arg_enable_ccache" ]]; then
|
|
echo "ENABLE_CCACHE := 1"
|
|
fi
|
|
|
|
# Include base
|
|
echo ""
|
|
echo "include \$(SRCDIR)/Makefile.in"
|
|
} >> "$MAKEFILE"
|
|
|
|
stat "Created $MAKEFILE, now run make to build."
|
|
stat " See README.md for make targets and instructions"
|
|
}
|
|
|
|
#
|
|
# Parse arguments
|
|
#
|
|
|
|
arg_steamrt="soldier"
|
|
arg_protonsdk_image="registry.gitlab.steamos.cloud/proton/soldier/sdk:0.20220119.0-1"
|
|
arg_no_protonsdk=""
|
|
arg_build_name=""
|
|
arg_container_engine=""
|
|
arg_docker_opts=""
|
|
arg_relabel_volumes=""
|
|
arg_enable_ccache=""
|
|
arg_help=""
|
|
invalid_args=""
|
|
function parse_args() {
|
|
local arg;
|
|
local val;
|
|
local val_used;
|
|
local val_passed;
|
|
while [[ $# -gt 0 ]]; do
|
|
arg="$1"
|
|
val=''
|
|
val_used=''
|
|
val_passed=''
|
|
if [[ -z $arg ]]; then # Sanity
|
|
err "Unexpected empty argument"
|
|
return 1
|
|
elif [[ ${arg:0:2} != '--' ]]; then
|
|
err "Unexpected positional argument ($1)"
|
|
return 1
|
|
fi
|
|
|
|
# Looks like an argument does it have a --foo=bar value?
|
|
if [[ ${arg%=*} != "$arg" ]]; then
|
|
val="${arg#*=}"
|
|
arg="${arg%=*}"
|
|
val_passed=1
|
|
else
|
|
# Otherwise for args that want a value, assume "--arg val" form
|
|
val="${2:-}"
|
|
fi
|
|
|
|
# The args
|
|
if [[ $arg = --help || $arg = --usage ]]; then
|
|
arg_help=1
|
|
elif [[ $arg = --build-name ]]; then
|
|
arg_build_name="$val"
|
|
val_used=1
|
|
elif [[ $arg = --container-engine ]]; then
|
|
arg_container_engine="$val"
|
|
val_used=1
|
|
elif [[ $arg = --docker-opts ]]; then
|
|
arg_docker_opts="$val"
|
|
val_used=1
|
|
elif [[ $arg = --relabel-volumes ]]; then
|
|
arg_relabel_volumes="1"
|
|
elif [[ $arg = --enable-ccache ]]; then
|
|
arg_enable_ccache="1"
|
|
elif [[ $arg = --proton-sdk-image ]]; then
|
|
val_used=1
|
|
arg_protonsdk_image="$val"
|
|
elif [[ $arg = --steam-runtime ]]; then
|
|
val_used=1
|
|
arg_steamrt="$val"
|
|
elif [[ $arg = --no-proton-sdk ]]; then
|
|
arg_no_protonsdk=1
|
|
else
|
|
err "Unrecognized option $arg"
|
|
return 1
|
|
fi
|
|
|
|
# Check if this arg used the value and shouldn't have or vice-versa
|
|
if [[ -n $val_used && -z $val_passed ]]; then
|
|
# "--arg val" form, used $2 as the value.
|
|
|
|
# Don't allow this if it looked like "--arg --val"
|
|
if [[ ${val#--} != "$val" ]]; then
|
|
err "Ambiguous format for argument with value \"$arg $val\""
|
|
err " (use $arg=$val or $arg='' $val)"
|
|
return 1
|
|
fi
|
|
|
|
# Error if this was the last positional argument but expected $val
|
|
if [[ $# -le 1 ]]; then
|
|
err "$arg takes a parameter, but none given"
|
|
return 1
|
|
fi
|
|
|
|
shift # consume val
|
|
elif [[ -z $val_used && -n $val_passed ]]; then
|
|
# Didn't use a value, but passed in --arg=val form
|
|
err "$arg does not take a parameter"
|
|
return 1
|
|
fi
|
|
|
|
shift # consume arg
|
|
done
|
|
}
|
|
|
|
usage() {
|
|
"$1" "Usage: $0 { --no-proton-sdk | --proton-sdk-image=<image> --steam-runtime=<name> }"
|
|
"$1" " Generate a Makefile for building Proton. May be run from another directory to create"
|
|
"$1" " out-of-tree build directories (e.g. mkdir mybuild && cd mybuild && ../configure.sh)"
|
|
"$1" ""
|
|
"$1" " Options"
|
|
"$1" " --help / --usage Show this help text and exit"
|
|
"$1" ""
|
|
"$1" " --build-name=<name> Set the name of the build that displays when used in Steam"
|
|
"$1" ""
|
|
"$1" " --container-engine=<engine> Which Docker-compatible container engine to use,"
|
|
"$1" " e.g. podman. Tries to do autodiscovery when not specified."
|
|
"$1" ""
|
|
"$1" " --docker-opts='<options>' Extra options to pass to Docker when invoking the runtime."
|
|
"$1" ""
|
|
"$1" " --relabel-volumes Bind-mounted volumes will be relabeled. Use with caution."
|
|
"$1" ""
|
|
"$1" " --enable-ccache Mount \$CCACHE_DIR or \$HOME/.ccache inside of the container and use ccache for the build."
|
|
"$1" ""
|
|
"$1" " Steam Runtime"
|
|
"$1" " Proton builds that are to be installed & run under the steam client must be built with"
|
|
"$1" " the Steam Runtime SDK to ensure compatibility. See README.md for more information."
|
|
"$1" ""
|
|
"$1" " --proton-sdk-image=<image> Automatically invoke the Steam Runtime SDK in <image>"
|
|
"$1" " for build steps that must be run in an SDK"
|
|
"$1" " environment. See README.md for instructions to"
|
|
"$1" " create this image."
|
|
"$1" " --steam-runtime=soldier Name of the steam runtime release to build for (soldier, scout)."
|
|
"$1" ""
|
|
"$1" " --no-proton-sdk Do not automatically invoke any runtime SDK as part of the build."
|
|
"$1" " Build steps may still be manually run in a runtime environment."
|
|
exit 1;
|
|
}
|
|
|
|
parse_args "$@" || usage err
|
|
[[ -z $arg_help ]] || usage info
|
|
|
|
# Sanity check arguments
|
|
if [[ -n $arg_no_protonsdk && -n $arg_protonsdk_image ]]; then
|
|
die "Cannot specify --proton-sdk-image as well as --no-proton-sdk"
|
|
elif [[ -z $arg_no_protonsdk && -z $arg_protonsdk_image ]]; then
|
|
die "Must specify either --no-proton-sdk or --proton-sdk-image"
|
|
fi
|
|
|
|
configure "$arg_protonsdk_image" "$arg_steamrt"
|