Skip to content

Instantly share code, notes, and snippets.

@jdek
Created October 23, 2016 18:43
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 jdek/f7f3b76d780b1c271171d44bb0858c03 to your computer and use it in GitHub Desktop.
Save jdek/f7f3b76d780b1c271171d44bb0858c03 to your computer and use it in GitHub Desktop.
#!/bin/sh -e
DIR=$(cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P)
# Returns the number of processor cores available
# Usage: num_cpus
num_cpus()
{
# This *should* be available on literally everything, including OSX
getconf _NPROCESSORS_ONLN
}
# Extracts a file based on its extension
# Usage: extract <archive> <out?> <strip?>
auto_extract()
{
out=
if [ "$#" -gt 1 ]; then
out="-C $2"
mkdir -p "$2"
fi
if [ "$#" -gt 1 ]; then
out="$out --strip-components=$3"
fi
path=$1
name=$(echo $path|sed -e "s/.*\///")
ext=$(echo $name|sed -e "s/.*\.//")
echo "Extracting $name..."
case $ext in
"tar") tar --no-same-owner -xf $path $out ;;
"gz"|"tgz") tar --no-same-owner -xzf $path $out ;;
"bz2"|"tbz2") tar --no-same-owner -xjf $path $out ;;
"xz"|"txz") tar --no-same-owner -xJf $path $out ;;
"zip")
unzip $path
;;
*) echo "I don't know how to extract $ext archives!"; return 1 ;;
esac
return $?
}
# Downloads and extracts a file, with some extra checks.
# Usage: download_and_extract <url> <output?> <strip?>
download_and_extract()
{
url=$1
name=$(echo $url|sed -e "s/.*\///")
outdir=$2
strip=$3
[ -d $outdir ] && echo "Already extracted $outdir..." && return 0
# First, if the archive already exists, attempt to extract it. Failing
# that, attempt to continue an interrupted download. If that also fails,
# remove the presumably corrupted file.
[ -f $name ] && { auto_extract $name $outdir $strip && return 0; } || { wget --continue --no-check-certificate $url -O $name || rm -f $name; }
# If the file does not exist at this point, it means it was either never
# downloaded, or it was deleted for being corrupted. Just go ahead and
# download it.
# Using wget --continue here would make buggy servers flip out for nothing.
[ -f $name ] || wget --no-check-certificate $url -O $name && auto_extract $name $outdir $strip
}
# Clones or updates a Git repository.
# Usage: clone_git_repo <hostname> <user> <repo> <branch>
clone_git_repo()
{
host=$1
user=$2
repo=$3
branch=${4:-master}
OLDPWD=$PWD
# Try to update an existing repository at the target path.
# Nuke it if it's corrupted and the pull fails.
[ -d $repo/.git ] && { cd $repo && echo "Updating $repo..." && git pull; }
# The above command may leave us standing in the existing repo.
cd $OLDPWD
# If it does not exist at this point, it was never there in the first place
# or it was nuked due to being corrupted. Clone and track master, please.
# Attempt to clone over SSH if possible, use anonymous HTTP as fallback.
# Set SSH_ASKPASS and stdin(<) to prevent it from freezing to ask for auth.
[ -d $repo ] || SSH_ASKPASS=false git clone --recursive -b $branch git@$host:$user/$repo.git $repo < /dev/null || SSH_ASKPASS=false git clone --recursive -b $branch https://$host/$user/$repo.git $repo < /dev/null || return 1
}
download()
{
{ mkdir -p "$DIR/src" && cd "$DIR/src"; } || { echo "Couldn't create source dir."; exit 1; }
clone_git_repo github.com vitasdk newlib vita
clone_git_repo github.com vitasdk vita-toolchain master
clone_git_repo github.com vitasdk vita-headers master
clone_git_repo github.com vitasdk pthread-embedded master
clone_git_repo github.com Dead2 zlib-ng develop
download_and_extract http://www.digip.org/jansson/releases/jansson-2.7.tar.gz jansson 1
download_and_extract https://nih.at/libzip/libzip-1.1.3.tar.xz libzip 1
download_and_extract https://ftp.gnu.org/gnu/binutils/binutils-2.27.tar.bz2 binutils 1
download_and_extract http://www.mr511.de/software/libelf-0.8.13.tar.gz libelf 1
download_and_extract ftp://ftp.gnu.org/gnu/gcc/gcc-6.2.0/gcc-6.2.0.tar.bz2 gcc 1
# if we have isl then we probably have all the prerequisites
cd gcc && [ ! -f isl*.tar.bz2 ] && ./contrib/download_prerequisites
}
patch_libelf()
{
[ ! -f .libelf_patched ] && patch -p1 -N << 'EOF'
diff -ru a/libelf/configure b/src/libelf-0.8.13/configure
--- a/libelf/configure 2015-08-19 18:51:37.000000000 +0400
+++ b/libelf/configure 2015-09-22 20:37:30.000000000 +0400
@@ -1595,7 +1595,7 @@
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
- ac_cv_sizeof_long_long=0
+ ac_cv_sizeof_long_long=8
else
cat > conftest.$ac_ext <<EOF
#line 1602 "configure"
EOF
: > .libelf_patched
}
patch_binutils()
{
[ ! -f .binutils_patched ] && patch -p1 -N << 'EOF'
diff -ru a/binutils/ld/scripttempl/elf.sc b/src/binutils/ld/scripttempl/elf.sc
--- a/binutils/ld/scripttempl/elf.sc 2015-08-19 18:51:37.000000000 +0400
+++ b/binutils/ld/scripttempl/elf.sc 2015-09-22 20:37:30.000000000 +0400
@@ -536,7 +536,8 @@
${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
-
+ /* Hacky hackity hack. Need this because otherwise data segment is not aligned enough. */
+ . = ALIGN(0x10000);
/* Exception handling */
.eh_frame ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
EOF
: > .binutils_patched
}
patch_gcc()
{
[ ! -f .gcc_patched ] && cat patch -p1 << 'EOF'
--- a/gcc/gcc/config/arm/arm.h 2016-04-01 15:58:53.000000000 +0100
+++ b/gcc/gcc/config/arm/arm.h 2016-10-23 13:32:10.000000000 +0100
@@ -45,7 +45,10 @@
extern char arm_arch_name[];
/* Target CPU builtins. */
-#define TARGET_CPU_CPP_BUILTINS() arm_cpu_cpp_builtins (pfile)
+#define TARGET_CPU_CPP_BUILTINS() do { \
+ builtin_define ("__vita__"); \
+ arm_cpu_cpp_builtins (pfile) \
+} while (0)
#include "config/arm/arm-opts.h"
--- a/gcc/gcc/gcc.c 2016-08-15 12:19:34.000000000 +0100
+++ b/gcc/gcc/gcc.c 2016-10-23 13:29:23.000000000 +0100
@@ -658,8 +658,9 @@
#endif
/* config.h can define LIB_SPEC to override the default libraries. */
+#undef LIB_SPEC
#ifndef LIB_SPEC
-#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} -lSceRtc_stub -lSceKernel_stub -lSceNet_stub"
#endif
/* When using -fsplit-stack we need to wrap pthread_create, in order
EOF
: > .gcc_patched
}
build()
{
GCC_CONFIGURE="--disable-multilib --with-arch=armv7-a --with-tune=cortex-a9 --with-fpu=neon --with-float=hard --with-mode=thumb"
VITADEV=/usr/local/vitadev
PKGVERSION="GNU Toolchain PS Vita (https://github.com/vitadev/vitatoolchain)"
cd "$DIR"
{ mkdir -p build && cd build && mkdir -p _prefix; } || { echo "Couldn't create build dir."; exit 1; }
if [ $# -lt 1 ]; then
build jansson libelf zlib libzip vita-toolchain binutils gcc-bootstrap vita-libs newlib pthreads gcc
fi
while [[ $# > 0 ]] ; do
{ mkdir -p "$1" && cd "$1"; } || { echo "Couldn't create build dir $1."; exit 1; }
case "$1" in
jansson)
"$DIR/src/jansson/configure" --disable-shared --enable-static --prefix="$DIR/build/_prefix"
make install
;;
libelf)
cd $DIR/src
patch_libelf
cd -
"$DIR/src/libelf/configure" --disable-shared --enable-static --prefix="$DIR/build/_prefix"
make install
;;
zlib)
"$DIR/src/zlib-ng/configure" --static --prefix="$DIR/build/_prefix"
make install
;;
libzip)
"$DIR/src/libzip/configure" --disable-shared --enable-static --prefix="$DIR/build/_prefix"
make install
;;
vita-toolchain)
cmake "$DIR/src/vita-toolchain" \
-DJansson_INCLUDE_DIR="$DIR/build/_prefix/include/" \
-DJansson_LIBRARY="$DIR/build/_prefix/lib/libjansson.a" \
-Dlibelf_INCLUDE_DIR="$DIR/build/_prefix/include/" \
-Dlibelf_LIBRARY="$DIR/build/_prefix/lib/libelf.a" \
-Dzlib_INCLUDE_DIR="$DIR/build/_prefix/include/" \
-Dzlib_LIBRARY="$DIR/build/_prefix/lib/libz.a" \
-Dlibzip_INCLUDE_DIR="$DIR/build/_prefix/include/" \
-Dlibzip_CONFIG_INCLUDE_DIR="$DIR/build/_prefix/lib/libzip/include/" \
-Dlibzip_LIBRARY="$DIR/build/_prefix/lib/libzip.a" \
-DUSE_BUNDLED_ENDIAN_H=ON \
-DCMAKE_INSTALL_PREFIX="$VITADEV" \
-DDEFAULT_JSON="../share/db.json"
make
make install
;;
binutils)
cd $DIR/src
patch_binutils
cd -
"$DIR/src/binutils/configure" \
--target=arm-vita-eabi \
--prefix="$VITADEV" \
--disable-nls \
--disable-werror \
--enable-interwork \
--enable-plugins \
--with-sysroot="$VITADEV/arm-vita-eabi" \
"--with-pkgversion=$PKGVERSION"
make
make install
;;
gcc-bootstrap)
cd $DIR/src
patch_gcc
cd -
EXTRA_CFLAGS="-fbracket-depth=512"
EXTRA_CXXFLAGS="-fbracket-depth=512"
"$DIR/src/gcc/configure" --target=arm-vita-eabi \
--prefix="$VITADEV" \
--enable-languages=c,c++ \
--disable-decimal-float \
--disable-libffi \
--disable-libgomp \
--disable-libmudflap \
--disable-libquadmath \
--disable-libssp \
--disable-libstdcxx-pch \
--disable-nls \
--disable-shared \
--disable-threads \
--disable-tls \
--with-newlib \
--without-headers \
--with-gnu-as \
--with-gnu-ld \
--with-sysroot="$VITADEV/arm-vita-eabi" \
"--with-pkgversion=$PKGVERSION" \
CFLAGS="${EXTRA_CFLAGS}" \
CXXFLAGS="${EXTRA_CXXFLAGS}" \
${GCC_CONFIGURE}
make all-gcc
make install-gcc
;;
vita-libs)
"$VITADEV/bin/vita-libs-gen" "$DIR/src/vita-headers/db.json" .
make ARCH="$VITADEV/bin/arm-vita-eabi"
cp *.a "$VITADEV/arm-vita-eabi/lib/"
cp -r "$DIR/src/vita-headers/include" "$VITADEV/arm-vita-eabi/"
mkdir -p "$VITADEV/arm-vita-eabi/share"
cp "$DIR/src/vita-headers/db.json" "$VITADEV/share"
;;
newlib)
"$DIR/src/newlib/configure" \
--target=arm-vita-eabi \
--prefix="$VITADEV" \
--enable-newlib-io-long-long \
--enable-newlib-register-fini \
--disable-newlib-supplied-syscalls \
--disable-nls
make
make install
;;
pthreads)
make -C "$DIR/src/pthread-embedded/platform/vita/"
PREFIX="$VITADEV/arm-vita-eabi" make -C "$DIR/src/pthread-embedded/platform/vita/" install
;;
gcc)
cd $DIR/src
patch_gcc
cd -
EXTRA_CFLAGS="-fbracket-depth=512"
EXTRA_CXXFLAGS="-fbracket-depth=512"
"$DIR/src/gcc/configure" --target=arm-vita-eabi \
--prefix="$VITADEV" \
--enable-languages=c,c++ \
--enable-plugins \
--enable-threads=posix \
--disable-decimal-float \
--disable-libffi \
--disable-libgomp \
--disable-libmudflap \
--disable-libquadmath \
--disable-libssp \
--disable-libstdcxx-pch \
--disable-nls \
--disable-shared \
--disable-tls \
--with-gnu-as \
--with-gnu-ld \
--with-newlib \
--with-headers=yes \
--with-sysroot="$VITADEV/arm-vita-eabi" \
CFLAGS="${EXTRA_CFLAGS}" \
CXXFLAGS="${EXTRA_CXXFLAGS}" \
${GCC_CONFIGURE}
make
make install
;;
esac
cd -
shift
done
}
clean()
{
cd "$DIR"
rm -rf build
}
package()
{
echo "Not implemented"
exit 1
}
if [ "$#" -lt 1 ]; then
echo "$0: vitadev toolchain buildscript"
echo -e "\tdownload"
echo -e "\t\tDownload all the sources."
echo -e "\tmake"
echo -e "\t\tBuild, and install toolchain."
echo -e "\tclean"
echo -e "\t\tClean the toolchain build."
echo -e "\tall"
echo -e "\t\tMake and package the toolchain."
echo -e "\tpackage"
echo -e "\t\tPackage the toolchain as a tarball for your architecture."
exit 1
fi
while [[ $# > 0 ]] ; do
case "$1" in
download)
download
;;
build)
build ${2}
;;
clean)
clean
;;
package)
package
;;
all)
build
package
;;
esac
shift
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment