# 02 - Building toolchain with pkgupd

> PKGUPD is a better package manager and successor of appctl in rlxos, PKGUPD aims to be a modular/extensible package manager whose functionality can be increase using the modules

Please check [Introduction to PKGUPD](https://blog.rlxos.dev/01-introduction-to-pkgupd-ckr1s6kxp0ffhqus1b4fyeelr)

In this guide, we write will a  [recipe](https://blog.rlxos.dev/01-introduction-to-pkgupd-ckr1s6kxp0ffhqus1b4fyeelr)  file for PKGUPD to generate a cross-compiler toolchain with
-  [musl libc](https://www.gnu.org/software/libc/) 
-  [gcc](https://gcc.gnu.org/) 
-  [binutils](https://www.gnu.org/software/binutils/)

# Prerequiesties and Targeted Audience
You need to have a basic idea of toolchains, Unix systems, and compilation. This guide targets the Embedded software developer or basically those how need to set up a cross-compiler.

# Cross Compiler Toolchain
A cross compiler is a compiler capable of creating executable code for a platform other than the one on which the compiler is running, which means you are using a system of architecture Type 'A' and compiles your software to work on System 'B'.

For example, you are coding on a Linux system and want to compile your apps for Android, Windows, or raspberry pi.

## Build Variable
| Variable ID | Description | Example Value |
| ----------- | ------------ | ---------------|
| TARGET | Triplet triplet for which we are building our cross-compile | aarch64-linux, [Learn More](https://wiki.osdev.org/Target_Triplet)  |
| CARCH | Architecture of target system | x86_64, i686, arm |
| ROOTS | Root Directory for target system | /roots-x86_64 |
| TCDIR | Directory where toolchain we are going to install our toolchain | /toolchain-x86_64 |
| FILES | Directory path for patches or extra files | -- |

```yaml
environ:
  - CARCH="<Replace-this-with-target-arch>"
  - TARGET="<Replace-this-with-target-triplet>"
  - TCDIR="$(pwd)/toolchain-${CARCH}"
  - ROOTS="$(pwd)/roots-${CARCH}"
  - PATH="${TCDIR}/bin:${PATH}"
```

## Binutils
In this part we define a package for binutils which is our cross assembler and linker
```yaml
- id: binutils
  sources:
    - https://ftp.gnu.org/gnu/binutils/binutils-2.37.tar.xz
  dir: binutils-2.37
  flags:
    - id: configure
      only: true
      value: >
        --prefix=${TCDIR}
        --with-sysroot=${ROOTS}
        --target=${TARGET}
        --disable-multilib
        --disable-nls
        --disable-werror
```
| Flag | About |
| ---- | ---- | 
| prefix | This tell the configure script to prepare the program install in ${TCDIR}  directory |
| with-sysroot | This tell the build system to look of libraries in ${ROOTS} directory |
| target | Set the target triplet |
| disable-multilib | We have no need of multilib at this stage. |
| disable-nls | Disable internationalization |
| disable-werror | Disable warning on errors |


## GCC Static
In this part we define the static build of gcc which is our cross-compiler
```yaml
- id: gcc-static
  sources:
    - https://ftp.gnu.org/gnu/gcc/gcc-11.1.0/gcc-11.1.0.tar.xz
    - https://www.mpfr.org/mpfr-4.1.0/mpfr-4.1.0.tar.xz
    - https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz
    - https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz
  dir: gcc-11.1.0
  flags:
    - id: configure
      only: true
      value: >
        --prefix=${TCDIR}
        --with-sysroot=${ROOTS}
        --target=${TARGET}
        --with-glibc-version=2.11
        --with-newlib
        --without-headers
        --enable-initfini-array
        --disable-nls
        --disable-shared
        --disable-multilib
        --disable-decimal-float
        --disable-threads
        --disable-libatomic
        --disable-libgomp
        --disable-libquadmath
        --disable-libssp
        --disable-libvtv
        --disable-libstdcxx
        --enable-languages=c
  postscript: |
    cat gcc/limitx.h gcc/glimits.h gcc/limity.h > `dirname $($TARGET-gcc -print-libgcc-file-name)`/install-tools/include/limits.h
```

## Kernel Headers
Linux API Headers expose the kernel's API for use by Glibc.
```yaml
- id: api-headers
  sources:
    - https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.13.4.tar.xz
  dir: linux-5.13.4
  plugin: script
  script: |
    make mrproper
    make headers
    find usr/include -name ".*" -delete
    rm usr/include/Makefile
    cp -rv usr/include ${ROOTS}/usr
```

## Glibc
In this part we define the GNU Libc library which is our standard C library
```yaml
- id: glibc
  sources:
    - https://ftp.gnu.org/gnu/glibc/glibc-2.33.tar.xz
  dir: glibc-2.33
  environ:
    - DESTDIR=${ROOTS}

  flags:
    - id: configure
      only: true
      value: >
        --prefix=/usr
        --host=${TARGET}
        --build=$(../scripts/config.guess)
        --enable-kernel=3.2
        --with-headers=$LFS/usr/include
        libc_cv_slibdir=/usr/lib
```

# Complete recipe file
```yaml
id: cross-toolchain
version: 0.0.1
about: Cross compiler toolchain

clean: true
split: false
compile: true
environ:
  - CARCH="<Replace-this-with-target-arch>"
  - TARGET="<Replace-this-with-target-triplet>"
  - TCDIR="$(pwd)/toolchain-${CARCH}"
  - ROOTS="$(pwd)/roots-${CARCH}"
  - PATH="${TCDIR}/bin:${PATH}"

packages:
  - id: binutils
    sources:
      - https://ftp.gnu.org/gnu/binutils/binutils-2.37.tar.xz
    dir: binutils-2.37
    flags:
      - id: configure
        only: true
        value: >
          --prefix=${TCDIR}
          --with-sysroot=${ROOTS}
          --target=${TARGET}
          --disable-multilib
          --disable-nls
          --disable-werror

  - id: gcc-static
    sources:
      - https://ftp.gnu.org/gnu/gcc/gcc-11.1.0/gcc-11.1.0.tar.xz
      - https://www.mpfr.org/mpfr-4.1.0/mpfr-4.1.0.tar.xz
      - https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz
      - https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz
    dir: gcc-11.1.0
    flags:
      - id: configure
        only: true
        value: >
          --prefix=${TCDIR}
          --with-sysroot=${ROOTS}
          --target=${TARGET}
          --with-glibc-version=2.11
          --with-newlib
          --without-headers
          --enable-initfini-array
          --disable-nls
          --disable-shared
          --disable-multilib
          --disable-decimal-float
          --disable-threads
          --disable-libatomic
          --disable-libgomp
          --disable-libquadmath
          --disable-libssp
          --disable-libvtv
          --disable-libstdcxx
          --enable-languages=c
    postscript: |
      cat gcc/limitx.h gcc/glimits.h gcc/limity.h > `dirname $($TARGET-gcc -print-libgcc-file-name)`/install-tools/include/limits.h

  - id: api-headers
    sources:
      - https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.13.4.tar.xz
    dir: linux-5.13.4
    plugin: script
    script: |
      make mrproper
      make headers
      find usr/include -name ".*" -delete
      rm usr/include/Makefile
      cp -rv usr/include ${ROOTS}/usr

  - id: glibc
    sources:
      - https://ftp.gnu.org/gnu/glibc/glibc-2.33.tar.xz
    dir: glibc-2.33
    environ:
      - DESTDIR=${ROOTS}

    flags:
      - id: configure
        only: true
        value: >
          --prefix=/usr
          --host=${TARGET}
          --build=$(../scripts/config.guess)
          --enable-kernel=3.2
          --with-headers=$LFS/usr/include
          libc_cv_slibdir=/usr/lib
```

## Start build
Execute the build process with below command:
```bash
pkgupd install ./toolchain.yml
```

