libretro-super/libretro-build-common.sh

456 lines
13 KiB
Bash

# vim: set ts=3 sw=3 noet ft=sh : bash
. "$BASE_DIR/script-modules/log.sh"
. "$BASE_DIR/script-modules/util.sh"
. "$BASE_DIR/script-modules/fetch-rules.sh"
. "$BASE_DIR/script-modules/cpu.sh"
. "$BASE_DIR/script-modules/module_base.sh"
. "$BASE_DIR/rules.d/core-rules.sh"
die() {
echo $1
#exit 1
}
#
# Regarding COMPILER... It didn't used to be safe. Now it is, provided that
# you are using it in a command line passed to echo_cmd without additional
# quoting, like so:
#
# echo_cmd "$MAKE TARGET=\"libretro\" $COMPILER OTHERVAR=\"$SOMETHING\""
#
if [ "${CC}" ] && [ "${CXX}" ]; then
COMPILER="CC=\"${CC}\" CXX=\"${CXX}\""
else
COMPILER=""
fi
echo "Compiler: CC=\"$CC\" CXX=\"$CXX\""
[[ "${ARM_NEON}" ]] && echo '=== ARM NEON opts enabled... ===' && export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-neon"
[[ "${CORTEX_A8}" ]] && echo '=== Cortex A8 opts enabled... ===' && export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-cortexa8"
[[ "${CORTEX_A9}" ]] && echo '=== Cortex A9 opts enabled... ===' && export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-cortexa9"
[[ "${ARM_HARDFLOAT}" ]] && echo '=== ARM hardfloat ABI enabled... ===' && export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-hardfloat"
[[ "${ARM_SOFTFLOAT}" ]] && echo '=== ARM softfloat ABI enabled... ===' && export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-softfloat"
[[ "$X86" ]] && echo '=== x86 CPU detected... ==='
[[ "$X86" ]] && [[ "$X86_64" ]] && echo '=== x86_64 CPU detected... ==='
[[ "${IOS}" ]] && echo '=== iOS =='
echo "$FORMAT_COMPILER_TARGET"
echo "$FORMAT_COMPILER_TARGET_ALT"
RESET_FORMAT_COMPILER_TARGET=$FORMAT_COMPILER_TARGET
RESET_FORMAT_COMPILER_TARGET_ALT=$FORMAT_COMPILER_TARGET_ALT
# FIXME: We should use the theos toolchain without their make system which is
# buggy on Linux and doesn't do what we want anyway. It'd remove need
# for this and other hacks.
CORE_PREFIX=""
CORE_SUFFIX="_libretro${FORMAT}.$FORMAT_EXT"
if [ "$platform" = "theos_ios" ]; then
CORE_PREFIX="objs/obj/"
fi
post_error_log() {
error=`cat $WORKDIR/log/$1.log | tail -n 100`
haste=`curl -s -XPOST http://paste.libretro.com/ -d"$error"`
haste=`echo $haste | cut -d"\"" -f4`
echo "$1: [status: fail ] (platform: $FORMAT_COMPILER_TARGET) LOG: http://paste.libretro.com/$haste"
}
build_summary_log() {
# Trailing spaces are intentional here
if [ "$1" -eq "0" ]; then
export build_success="$build_success$2 "
else
export build_fail="$build_fail$2 "
#post_error_log $2
fi
}
copy_core_to_dist() {
[ -z "$1" ] && return 1
dest="${2:-$1}"
if [ "$FORMAT_ABI_ANDROID" = "yes" ]; then
echo_cmd "cp \"$CORE_PREFIX$1$CORE_SUFFIX\" \"$RARCH_DIST_DIR/${dest}_libretro_android.so\""
else
echo_cmd "cp \"$CORE_PREFIX$1$CORE_SUFFIX\" \"$RARCH_DIST_DIR/$dest$CORE_SUFFIX\""
fi
ret=$?
build_summary_log $ret "$dest"
return $ret
}
build_should_skip() {
[ -z "$SKIP_UNCHANGED" ] && return 1
[ -z "$BUILD_REVISIONS_DIR" ] && BUILD_REVISIONS_DIR="$WORKDIR/build-revisions"
build_revision_file="$BUILD_REVISIONS_DIR/$1"
[ ! -r "$build_revision_file" ] && return 1
read previous_revision < "$build_revision_file"
[ "$previous_revision" != "$(fetch_revision $2)" ] && return 1
return 0
}
build_save_revision() {
[ -z "$SKIP_UNCHANGED" ] && return
[ "$1" != "0" ] && return
echo $(fetch_revision) > "$BUILD_REVISIONS_DIR/$2"
}
check_opengl() {
if [ "$BUILD_LIBRETRO_GL" ]; then
if [ "$ENABLE_GLES" ]; then
echo '=== OpenGL ES enabled ==='
export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-gles"
export FORMAT_COMPILER_TARGET_ALT="$FORMAT_COMPILER_TARGET"
else
echo '=== OpenGL enabled ==='
export FORMAT_COMPILER_TARGET="$FORMAT_COMPILER_TARGET-opengl"
export FORMAT_COMPILER_TARGET_ALT="$FORMAT_COMPILER_TARGET"
fi
else
echo '=== OpenGL disabled in build ==='
return 1
fi
return 0
}
reset_compiler_targets() {
export FORMAT_COMPILER_TARGET=$RESET_FORMAT_COMPILER_TARGET
export FORMAT_COMPILER_TARGET_ALT=$RESET_FORMAT_COMPILER_TARGET_ALT
}
# $1 is corename
# $2 is subcorename
# $3 is subdir. In case there is no subdir, enter "." here
# $4 is Makefile name
# $5 is preferred platform
build_libretro_generic_makefile_subcore() {
build_dir="$WORKDIR/libretro-$1"
if [ -d "$build_dir" ]; then
echo "=== Building $2 ==="
echo_cmd "cd \"$build_dir/$3\""
if [ -z "$NOCLEAN" ]; then
echo_cmd "$MAKE -f \"$4\" platform=$5 -j$JOBS clean" || die "Failed to clean $2"
fi
echo_cmd "$MAKE -f $4 platform=$5 -j$JOBS" || die "Failed to build $2"
copy_core_to_dist "$2"
fi
}
build_libretro_generic() {
echo_cmd "cd \"$5/$2\""
if [ -z "$NOCLEAN" ]; then
echo_cmd "$MAKE -f \"$3\" platform=\"$4\" \"-j$JOBS\" clean" || die "Failed to clean $1"
fi
echo_cmd "$MAKE -f \"$3\" platform=\"$4\" $COMPILER \"-j$JOBS\"" || die "Failed to build $1"
}
# build_libretro_generic_makefile
#
# $1 Name of the core
# $2 Subdirectory of makefile (use "." for none)
# $3 Name of makefile
# $4 Either FORMAT_COMPILER_TARGET or an alternative
# $5 Skip copying (for cores that don't produce exactly one core)
build_libretro_generic_makefile() {
build_dir="$WORKDIR/libretro-$1"
if build_should_skip $1 "$build_dir"; then
echo "Core $1 is already built, skipping..."
return
fi
if [ -d "$build_dir" ]; then
echo "=== Building $1 ==="
build_libretro_generic $1 "$2" "$3" $4 "$build_dir"
if [ -z "$5" ]; then
copy_core_to_dist $1
build_save_revision $? $1
fi
else
echo "$1 not fetched, skipping ..."
fi
}
# build_makefile
#
# $core_build_subdir Subdir of the makefile (if any)
# $core_build_makefile Name of the makefile (if not {GNUm,m,M}akefile)
# $core_build_args Extra arguments to make
# $core_build_platform Usually some variant of $FORMAT_COMPILER_TARGET
# $core_build_cores A list of cores produced by the builds
build_makefile() {
[ -n "$core_build_subdir" ] && core_build_subdir="/$core_build_subdir"
make_cmdline="$MAKE"
if [ -n "$core_build_makefile" ]; then
make_cmdline="$make_cmdline -f $core_build_makefile"
fi
# TODO: Do $platform type stuff better (requires modding each core)
make_cmdline="$make_cmdline platform=\"$core_build_platform\""
[ -n "$STATIC_LINKING" ] && make_cmdline="$make_cmdline STATIC_LINKING=1"
[ -n "$JOBS" ] && make_cmdline="$make_cmdline -j$JOBS"
[ -n "$DEBUG" ] && make_cmdline="$make_cmdline DEBUG=$DEBUG"
build_dir="$WORKDIR/$core_dir$core_build_subdir"
if build_should_skip $1 "$build_dir"; then
echo "Core $1 is already built, skipping..."
return
fi
if [ -d "$build_dir" ]; then
echo_cmd "cd \"$build_dir\""
$core_build_configure
if [ -z "$NOCLEAN" ]; then
$core_build_preclean
echo_cmd "$make_cmdline $core_build_args clean"
fi
make_cmdline="$make_cmdline $COMPILER"
$core_build_prebuild
echo_cmd "$make_cmdline $core_build_args"
# TODO: Make this a separate stage/package rule
$core_build_prepkg
for a in $core_build_cores; do
copy_core_to_dist ${core_build_products:+$core_build_products/}$a $a
done
else
echo "$1 not fetched, skipping ..."
fi
}
# build_cmake
#
# $core_build_subdir Subdir of the makefile (if any)
# $core_build_args Extra arguments to cmake
# $core_build_extradir Location of the binary under build/
# $core_build_cores A list of cores produced by the builds
build_cmake() {
[ -n "$core_build_subdir" ] && core_build_subdir="/$core_build_subdir"
make_cmdline="cmake"
build_dir="$WORKDIR/$core_dir$core_build_subdir"
if build_should_skip $1 "$build_dir"; then
echo "Core $1 is already built, skipping..."
return
fi
if [ -d "$build_dir" ]; then
echo_cmd "cd \"$build_dir\""
$core_build_configure
if [ -z "$NOCLEAN" ]; then
$core_build_preclean
echo_cmd "$make_cmdline --build build --target clean"
fi
make_cmdline1="$make_cmdline $core_build_args . -Bbuild"
make_cmdline2="$make_cmdline --build build/ --target $core_cmake_target --config Release -- "
[ -n "$JOBS" ] && make_cmdline2="$make_cmdline2 -j$JOBS"
[ -n "$DEBUG" ] && make_cmdline2="$make_cmdline2 DEBUG=$DEBUG"
$core_build_prebuild
echo_cmd "$make_cmdline1"
echo_cmd "$make_cmdline2"
# TODO: Make this a separate stage/package rule
$core_build_prepkg
for a in $core_build_cores; do
copy_core_to_dist ${core_build_products:+$core_build_products/}build/${core_build_extradir:-}$a $a
done
else
echo "$1 not fetched, skipping ..."
fi
}
# libretro_build_core: Build the given core using its build rules
#
# $1 Name of the core to build
libretro_build_core() {
local opengl_type
if [ -n "${LIBRETRO_LOG_MODULE}" ]; then
printf -v log_module "$LIBRETRO_LOG_DIR/$LIBRETRO_LOG_MODULE" "$1"
[ -z "$LIBRETRO_LOG_APPEND" ] && : > "$log_module"
fi
eval "core_name=\${libretro_${1}_name:-$1}"
echo "$(color 34)=== $(color 1)$core_name$(color)"
lecho "=== $core_name"
eval "core_build_rule=\${libretro_${1}_build_rule:-generic_makefile}"
eval "core_dir=\${libretro_${1}_dir:-libretro-$1}"
eval "core_build_opengl=\$libretro_${1}_build_opengl"
if [ -n "$core_build_opengl" ]; then
if [[ "$core_build_opengl" = "yes" || "$core_build_opengl" = "optional" ]]; then
if [ -n "$BUILD_LIBRETRO_GL" ]; then
if [ -n "$ENABLE_GLES" ]; then
opengl_type="-gles"
else
opengl_type="-opengl"
fi
else
if [ "$core_build_opengl" = "yes" ]; then
echo "$1 requires OpenGL (which is disabled), skipping..."
return 0
fi
fi
else
echo "libretro_build_core:Unknown OpenGL setting for $1: \"$core_build_opengl\"."
return 1
fi
fi
echo "Building ${1}..."
lecho "Building ${1}..."
if [ -n "$log_module" ]; then
exec 6>&1
echo "Building ${1}..." >> "$log_module"
# TODO: Possibly a shell function for tee?
if [[ -n "$LIBRETRO_DEVELOPER" && -n "${cmd_tee:=$(find_tool "tee")}" ]]; then
exec > >($cmd_tee -a "$log_module")
else
exec > "$log_module"
fi
fi
case "$core_build_rule" in
generic_makefile)
# As of right now, only configure is used for now...
if [ "$(type -t libretro_${1}_configure 2> /dev/null)" = "function" ]; then
eval "core_configure=libretro_${1}_configure"
else
eval "core_configure=do_nothing"
fi
eval "core_build_makefile=\$libretro_${1}_build_makefile"
eval "core_build_subdir=\$libretro_${1}_build_subdir"
eval "core_build_args=\$libretro_${1}_build_args"
# TODO: Really, change how all of this is done...
eval "core_build_platform=\${libretro_${1}_build_platform:-$FORMAT_COMPILER_TARGET}$opengl_type"
eval "core_build_cores=\${libretro_${1}_build_cores:-$1}"
eval "core_build_products=\$libretro_${1}_build_products"
build_makefile $1 2>&1
;;
cmake)
# As of right now, only configure is used for now...
if [ "$(type -t libretro_${1}_configure 2> /dev/null)" = "function" ]; then
eval "core_configure=libretro_${1}_configure"
else
eval "core_configure=do_nothing"
fi
eval "core_build_subdir=\$libretro_${1}_build_subdir"
eval "core_build_extradir=\$libretro_${1}_build_extradir"
eval "core_build_args=\$libretro_${1}_build_args"
# TODO: Really, change how all of this is done...
eval "core_build_platform=\${libretro_${1}_build_platform:-$FORMAT_COMPILER_TARGET}$opengl_type"
eval "core_build_cores=\${libretro_${1}_build_cores:-$1}"
eval "core_build_products=\$libretro_${1}_build_products"
eval "core_cmake_target=${1}_libretro"
build_cmake $1 2>&1
;;
legacy)
eval "core_build_legacy=\$libretro_${1}_build_legacy"
if [ -n "$core_build_legacy" ]; then
echo "Warning: $1 hasn't been ported to a modern build rule yet."
echo " Will build it using legacy \"$core_build_legacy\"..."
$core_build_legacy 2>&1
fi
;;
none)
echo "Don't have a build rule for $1, skipping..."
;;
*)
echo "libretro_build_core:Unknown build rule for $1: \"$core_build_rule\"." >&2
exit 1
;;
esac
if [ -n "$log_module" ]; then
exec 1>&6 6>&-
fi
}
build_libretro_test() {
build_dir="$WORKDIR/retroarch"
if build_should_skip "test" "$build_dir"; then
echo 'Core test is already built, skipping...'
return
fi
if [ -d "$build_dir" ]; then
echo '=== Building RetroArch test cores ==='
if check_opengl; then
build_libretro_generic "retroarch" "cores/libretro-test-gl" "Makefile" $FORMAT_COMPILER_TARGET "$build_dir"
copy_core_to_dist "testgl"
fi
build_libretro_generic "retroarch" "cores/libretro-test" "Makefile" $FORMAT_COMPILER_TARGET "$build_dir"
copy_core_to_dist "test"
# TODO: Check for more than test here...
build_save_revision $? "test"
else
echo "$1 not fetched, skipping ..."
fi
}
summary() {
# fmt is external and may not be available
fmt_output="$(find_tool "fmt")"
local num_success="$(numwords $build_success)"
local fmt_success="${fmt_output:+$(echo " $build_success" | $fmt_output)}"
local num_fail="$(numwords $build_fail)"
local fmt_fail="${fmt_output:+$(echo " $build_fail" | $fmt_output)}"
if [[ -z "$build_success" && -z "$build_fail" ]]; then
lsecho "No build actions performed."
return
fi
if [ -n "$build_success" ]; then
secho "$(color 32)$num_success core(s)$(color) successfully processed:"
lecho "$num_success core(s) successfully processed:"
lsecho "$fmt_success"
fi
if [ -n "$build_fail" ]; then
secho "$(color 31)$num_fail core(s)$(color) failed:"
lecho "$num_fail core(s) failed:"
lsecho "$fmt_fail"
fi
}
create_dist_dir() {
mkdir -p "$RARCH_DIST_DIR"
}
create_dist_dir