If you wish to build the toolchain yourself, beware that this process can get
pretty tedious unless you have a powerful enough computer with plenty of
threads to spare. A system with at least 4 to 8 total threads or more is
recommended. You may have better success building the toolchain in ArchLinux
especially if you want to build the most recent versions of GCC. Debian
Buster however, may have about the same chance of success in building as
using ArchLinux.

It is recommended to stick with GCC 7.4.0 and Binutils 2.31 as this is the
version PSn00bSDK is most tested with. Though generally, it doesn't hurt to
try out newer versions and has been known to work flawlessly without issue.

These instructions are only for Linux, though they can be adapted for
building in Windows using MSys2 or Cygwin64. Beware that libgcc cannot
be built under Windows as the libgcc build process depends on symlinks
which is not supported by the operating system and is not wrapped by Msys2
and Cygwin64. The only workaround is to first build GCC in Linux then copy
the libgcc.a library from it to the Windows build.


Make sure the following packages are installed prior to building:
* make
* texinfo
* mpfr (development libs, if your distro offers it in a separate package)
* isl (development libs, if your distro offers it in a separate package)
* gmp (development libs, if your distro offers it in a separate package)
* mpc (development libs, if your distro offers it in a separate package)
* build-essential or build-essentials, if you don't have GCC installed yet.


Building binutils:

Binutils must be built first as GCC depends on binutils built for the same
target architecture. In this case, to compile GCC targetting mipsel-unknown-elf,
there must be a build of binutils targetting mipsel-unknown-elf as well.

* Download binutils source files at ftp://ftp.gnu.org. Choose a version you
  wish to use with PSn00bSDK.
  
* Extract the contents of the archive, preferably in a directory named gcc
  for example.
  
* Create a directory named binutils-build inside the gcc directory. Do not
  create it inside the binutils directory with the source files.
  
* Enter the binutils-build directory and configure binutils from there
  with the following command line:

../binutils-<version>/configure --prefix=/usr/local/mipsel-unknown-elf \
--target=mipsel-unknown-elf --with-float=soft

Replace <version> with the version of binutils you wish to use. You may also
want to change the prefix argument to a path you prefer to have the toolchain
installed to (ie. somewhere within your home directory so you wouldn't need
root privileges to install).

* Run `make -j 4` to compile binutils (-j specifies how many simultaneous
  jobs to spawn at once, set it equal to the number of cores/threads your
  system has available to speed up compiling).
  
* Run `make install-strip` to install binutils to the path specified by the
  --prefix argument (requires root privileges if you install to /usr/local).


Building gcc:

With binutils built it should be possible to build the GCC compilers. Since
GCC is considerably larger than binutils, compile time is going to be much
longer so it's going to take a longer while to finish building.

* Download gcc source files at ftp://ftp.gnu.org and choose a version you
  wish to use with PSn00bSDK.

* Extract it to the same gcc directory you extracted binutils in.

* Create a directory named gcc-build inside the gcc directory.

* Enter the gcc-build directory and configure gcc from there with the
  following command line:

../gcc-<version>/configure --disable-nls --disable-libada --disable-libssp \
--disable-libquadmath --disable-libstdc++-v3 --target=mipsel-unknown-elf \
--prefix=/usr/local/mipsel-unknown-elf --with-float=soft \
--enable-languages=c,c++ --with-gnu-as --with-gnu-ld

Replace <version> with the version of gcc you downloaded. The prefix path
must match to what you've specified for binutils earlier, if you've decided
on a different path to install the toolchain to.

When building under Windows you must additionally specify --disable-libgcc, so
libgcc won't be built as it requires symlinks not supported by the host system.

* Run make in the same manner as you built binutils to build gcc.

* Run `make install-strip` to install gcc to the path specified by --prefix
  (may require root privileges if you set the prefix to /usr/local).
  
* Add a path to the bin directory of the toolchain into your PATH environment
  variable by adding the following line in your .bashrc file:
  
export PATH=$PATH:/usr/local/mipsel-unknown-elf/bin

Under Windows, you'll have to add the path to the PATH environment variable
through System Properties.


Updating the ldscript:

The following changes are required in order for basic C++ functionality to work
in PSn00bSDK. The changes define the constructor and deconstructor sections
which are required for the relevant support functions in PSn00bSDK's libc
library to be linked properly.

* Go to mipsel-unknown-elf/lib/ldscripts in the toolchain directory.
  
* Open elf32elmip.x in any text editor.

* Locate the .text definition (with the {} brackets) and place the following
  inside the bracket block:

__CTOR_LIST__ = .;
___CTOR_LIST__ = .;
LONG (((__CTOR_END__ - __CTOR_LIST__) / 4) - 2)
KEEP (*(SORT (.ctors.*)))
KEEP (*(.ctors))
LONG (0x00000000)
__CTOR_END__ = .;
. = ALIGN (0x10);

__DTOR_LIST__ = .;
___DTOR_LIST__ = .;
LONG (((__DTOR_END__ - __DTOR_LIST__) / 4) - 2)
KEEP (*(SORT (.dtors.*)))
KEEP (*(.dtors))
LONG (0x00000000)
__DTOR_END__ = .;
. = ALIGN (0x10);

* Save script changes.

Since there's no known way (at least to me, Lameguy64) to configure GCC to use
one of the scripts in ldscripts directory as a default, you must specify
the modified script during the linking stage of your projects with the -T
argument, when invoking mipsel-unknown-elf-ld.

Alternatively, you can make a copy of the ldscript file and modify it within
your project directory. This is especially useful when code overlaying is used.


Note regarding C++ support:

C++ support in PSn00bSDK only goes as far as basic classes, namespaces and
the ability to dynamically create and delete class objects at any point of
the program. The required dependencies are supplied by libc of libpsn00b.

Standard C++ libraries are not implemented and likely never going to be
implemented due to bloat concerns that it may introduce. Besides, the official
SDK lacks full C++ support as well.
