From 3ccfeffa321122228c67862b48ce0fe89630dbd9 Mon Sep 17 00:00:00 2001 From: John Schoenick Date: Mon, 20 Aug 2018 17:12:14 -0700 Subject: [PATCH] Add configure.sh / configuration step to generate final makefile --- build/makefile_base.mak | 62 ++++++++---- configure.sh | 210 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 19 deletions(-) create mode 100755 configure.sh diff --git a/build/makefile_base.mak b/build/makefile_base.mak index d237a039..84cd9e24 100644 --- a/build/makefile_base.mak +++ b/build/makefile_base.mak @@ -36,20 +36,44 @@ export CC export CXX # Local name of this build, for dist/install steps -BUILD_NAME := proton-localbuild -SRCDIR := .. +# TODO Let configure.sh set/propagate this +BUILD_NAME ?= proton-localbuild # Selected container mode shell -CONTAINER_SHELL_BASE = sudo docker run --rm --init -v $(HOME):$(HOME) -w $(CURDIR) \ - -v /etc/passwd:/etc/passwd:ro -u $(shell id -u):$(shell id -g) -h $(shell hostname) \ - -v /tmp:/tmp $(SELECTED_CONTAINER) /dev/init -sg -- /bin/bash -CONTAINER32 := steamrt-proton-dev32 -CONTAINER64 := steamrt-proton-dev -SELECTED_CONTAINER := $(CONTAINER32) -CONTAINER_SHELL32 := $(CONTAINER_SHELL_BASE) -SELECTED_CONTAINER := $(CONTAINER64) -CONTAINER_SHELL64 := $(CONTAINER_SHELL_BASE) -undefine SELECTED_CONTAINER +DOCKER_SHELL_BASE = sudo docker run --rm --init -v $(HOME):$(HOME) -w $(CURDIR) \ + -v /etc/passwd:/etc/passwd:ro -u $(shell id -u):$(shell id -g) -h $(shell hostname) \ + -v /tmp:/tmp $(SELECT_DOCKER_IMAGE) /dev/init -sg -- /bin/bash + +# If STEAMRT64_MODE/STEAMRT32_MODE is set, set the nested SELECT_DOCKER_IMAGE to the _IMAGE variable and eval +# DOCKER_SHELL_BASE with it to create the CONTAINER_SHELL setting. +ifeq ($(STEAMRT64_MODE),docker) + SELECT_DOCKER_IMAGE := $(STEAMRT64_IMAGE) + CONTAINER_SHELL64 := $(DOCKER_SHELL_BASE) +else ifneq ($(STEAMRT64_MODE),) + foo := $(error Unrecognized STEAMRT64_MODE $(STEAMRT64_MODE)) +endif +ifeq ($(STEAMRT32_MODE),docker) + SELECT_DOCKER_IMAGE := $(STEAMRT32_IMAGE) + CONTAINER_SHELL32 := $(DOCKER_SHELL_BASE) +else ifneq ($(STEAMRT32_MODE),) + foo := $(error Unrecognized STEAMRT32_MODE $(STEAMRT32_MODE)) +endif +undefine SELECT_DOCKER_IMAGE + +# If we're using containers to sub-invoke the various builds, jobserver won't work, have some silly auto-jobs +# controllable by SUBMAKE_JOBS. Not ideal. +ifneq ($(CONTAINER_SHELL32)$(CONTAINER_SHELL64),) + SUBMAKE_JOBS ?= 24 + MAKE := make -j$(SUBMAKE_JOBS) +endif + +# Use default shell if no STEAMRT_ variables setup a container to invoke. Commands will just run natively. +ifndef CONTAINER_SHELL64 + CONTAINER_SHELL64 := $(SHELL) +endif +ifndef CONTAINER_SHELL32 + CONTAINER_SHELL32 := $(SHELL) +endif $(info Testing configured 64bit container) ifneq ($(shell $(CONTAINER_SHELL64) -c "echo hi"), hi) @@ -60,11 +84,7 @@ ifneq ($(shell $(CONTAINER_SHELL32) -c "echo hi"), hi) $(error "Cannot run commands in 32bit container") endif -# FIXME Don't bother in native -SUBMAKE_JOBS ?= 24 -MAKE := make -j$(SUBMAKE_JOBS) - -# FIXME OS X-vs-others stuff +# TODO Used by build_proton for the OS X steps LIB_SUFFIX := "so" STRIP := strip FREETYPE32_CFLAGS := @@ -93,7 +113,7 @@ INSTALL_PROGRAM_FLAGS := # Many of the configure steps below depend on the makefile itself, such that they are dirtied by changing the recipes # that create them. This can be annoying when working on the makefile, building with NO_MAKEFILE_DEPENDENCY=1 disables # this. -MAKEFILE_DEP := ./Makefile +MAKEFILE_DEP := $(MAKEFILE_LIST) ifeq ($(NO_MAKEFILE_DEPENDENCY),1) MAKEFILE_DEP := endif @@ -176,7 +196,11 @@ $(OBJ_DIRS): # FIXME OS X-only targets freetype -.PHONY: all all64 all32 +.PHONY: all all64 all32 default + +# Produce a working dist directory by default +default: all dist +.DEFAULT_GOAL := default # FIXME ffmpeg is optional diff --git a/configure.sh b/configure.sh new file mode 100755 index 00000000..a7fbd3e8 --- /dev/null +++ b/configure.sh @@ -0,0 +1,210 @@ +#!/bin/bash + +set -eu + +SRCDIR="$(dirname "$0")" + +# 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="$(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 "$@"; "$@"; } + +# +# Configure +# + +THIS_COMMAND="$0 $*" # For printing, not evaling +MAKEFILE="./Makefile" + +function check_steamrt_image() { + local type="$1" + local name="$2" + + # nil nil -> no container + [[ -n $type || -n $name ]] || return 0; + + # Otherwise both needed + [[ -n $type && -n $name ]] || die "Steam Runtime SDK option must be of form type:image" + + # Type known? + [[ $type = docker ]] || die "Only supported Steam Runtime type is currently docker" + + # Name must be alphanumericish for dumping into makefile and sanity. + [[ $name =~ ^[a-zA-Z0-9_.-]+$ ]] || die "Runtime image name should be alphanumeric ($name)" +} + +# 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 steamrt64_type="${1%:*}" + local steamrt64_name="${1#*:}" + local steamrt32_type="${2%:*}" + local steamrt32_name="${2#*:}" + + check_steamrt_image "$steamrt64_type" "$steamrt64_name" + check_steamrt_image "$steamrt32_type" "$steamrt32_name" + + local srcdir="$(dirname "$0")" + + # Don't die after this point or we'll have rather unhelpfully deleted the Makefile + if [[ -e ./Makefile ]]; then + [[ -n $arg_force ]] || die "Makefile exists, use --force to reconfigure ($MAKEFILE)" + info "Makefile exists, --force given, removing" + cmd rm "$MAKEFILE" + fi + + echo >> "$MAKEFILE" "# Generated by: $THIS_COMMAND" + echo >> "$MAKEFILE" "" + echo >> "$MAKEFILE" "SRCDIR := $(escape_for_make "$srcdir")" + echo >> "$MAKEFILE" "STEAMRT64_MODE := $(escape_for_make "$steamrt64_type")" + echo >> "$MAKEFILE" "STEAMRT64_IMAGE := $(escape_for_make "$steamrt64_name")" + echo >> "$MAKEFILE" "STEAMRT32_MODE := $(escape_for_make "$steamrt32_type")" + echo >> "$MAKEFILE" "STEAMRT32_IMAGE := $(escape_for_make "$steamrt32_name")" + echo >> "$MAKEFILE" "" + echo >> "$MAKEFILE" "include \$(SRCDIR)/build/makefile_base.mak" + + stat "Created $MAKEFILE, clear to run make! See BUILDING.md for make targets and instructions" +} + +# +# Parse arguments +# + +arg_force="" +arg_steamrt32="" +arg_steamrt64="" +arg_no_steamrt="" +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 = --force ]]; then + arg_force=1 + elif [[ $arg = --steam-runtime32 ]]; then + val_used=1 + arg_steamrt32="$val" + elif [[ $arg = --steam-runtime64 ]]; then + val_used=1 + arg_steamrt64="$val" + elif [[ $arg = --no-steam-runtime ]]; then + arg_no_steamrt=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 && ! -n $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-steam-runtime | --steam-runtime32= --steam-runtime64= }" + "$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" " --force Overwrite Makefile if it already exists" + "$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 BUILDING.md for more information." + "$1" "" + "$1" " --steam-runtime64=docker: Automatically invoke the Steam Runtime SDK in " + "$1" " for build steps that must be run in an SDK" + "$1" " environment. See BUILDING.md for instructions to" + "$1" " create this image." + "$1" "" + "$1" " --steam-runtime32=docker: The 32-bit docker image to use for steps that require" + "$1" " a 32-bit environment. See --steam-runtime64." + "$1" "" + "$1" " --no-steam-runtime 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; +} + +[[ $# -gt 0 ]] || usage info +parse_args "$@" || usage err + +if [[ -n $arg_no_steamrt && (-n $arg_steamrt32 || -n $arg_steamrt64) ]]; then + die "Cannot specify a Steam Runtime SDK as well as --no-steam-runtime" +elif [[ -z $arg_no_steamrt && ( -z $arg_steamrt32 || -z $arg_steamrt64 ) ]]; then + die "Must specify either --no-steam-runtime or both --steam-runtime32 and --steam-runtime64" +fi + +configure "$arg_steamrt64" "$arg_steamrt32"