# Building OS

## Prerequisites

The project uses GN Build System, please ensure that you have `gn` binary. If your system doesn't have the build system, please visit [instructions how to get a GN binary](https://code.ayaantunio.me/ayaan/Custom-Operating-System/src/branch/master/docs/getting_gn.md)

### Getting QEMU

The project uses QEMU as a primary build and test target. Please follow [instructions how to get a QEMU binary](https://code.ayaantunio.me/ayaan/Custom-Operating-System/src/branch/master/docs/getting_qemu.md).

### Tools for MacOS

```bash
brew install --cask osxfuse

brew install coreutils qemu e2fsprogs nasm m4 autoconf libtool automake bash gcc@10 ninja

# install fuse-ext2
```

`fuse-ext2` is not available as homebrew formula, download [sources](https://github.com/alperakcan/fuse-ext2) and compile it following [instructions](https://apple.stackexchange.com/questions/226981/how-do-i-install-fuse-ext2-to-use-with-osxfuse).

*Notes*:

* Make sure you have `xcode-tools` installed.

</br>

### Tools for Linux (Ubuntu)

```bash
apt install build-essential curl libmpfr-dev libmpc-dev libgmp-dev e2fsprogs qemu-system-i386 qemu-utils nasm fuseext2 ninja
```

</br>



### Tools for Windows (WSL2)

**Setting up WSL2**

1. **Enable WSL2** (requires Windows 10 version 2004+ or Windows 11):

   ```powershell

   # Run in PowerShell as Administrator

   wsl --install

   ```

   This installs WSL2 with Ubuntu by default.  Reboot when prompted.



2. **Install Ubuntu from Microsoft Store** (if not auto-installed):

   - Open Microsoft Store

   - Search for "Ubuntu" (recommend Ubuntu 22.04 LTS)

   - Click "Get" and install



3. **Set WSL2 as default version** (if needed):

   ```powershell

   wsl --set-default-version 2

   ```



4. **Launch Ubuntu** from Start Menu and create a user account. 



**Installing Development Tools in WSL2**



Once inside your WSL2 Ubuntu terminal:



```bash

# Update package lists

sudo apt update && sudo apt upgrade -y



# Install build tools

sudo apt install build-essential curl libmpfr-dev libmpc-dev libgmp-dev \

                 e2fsprogs qemu-system-x86 qemu-system-arm qemu-system-misc \

                 qemu-utils nasm ninja-build git python3 python3-pip -y
```
**WSL2-Specific Notes**: 



* **File Performance**: Keep your project files within the WSL2 filesystem rather than Windows filesystem (`/mnt/c/... `) for much better I/O performance.

* **GUI Applications**: WSL2 supports GUI apps natively on Windows 11. On Windows 10, you may need an X server like VcXsrv for QEMU's graphical output.

* **Memory Limits**: WSL2 defaults to 50% of host RAM.  Create `%USERPROFILE%\.wslconfig` to adjust: 

  ```ini

  [wsl2]

  memory=8GB

  processors=4

  ```

* **Accessing WSL files from Windows**: Navigate to `\\wsl$\Ubuntu\home\<username>\` in File Explorer. 

* **Restarting WSL**:  If you encounter issues, restart WSL with `wsl --shutdown` in PowerShell, then relaunch. 



</br>

## Cross-compiler

xOS could be compiled both with GNU and LLVM toochains.

*Note* that in GNU world, every host/target combination has its own set of binaries, headers, libraries, etc. So, choose GNU Toolchain based on target architecture you want to compile the OS to.

### GNU Toolchain for MacOS

***x86***

```bash
brew install i686-elf-gcc
```

***x86-64***

```bash
brew install x86_64-elf-gcc
```

***Arm64***

```bash
brew install aarch64-elf-gcc
```

</br>

### LLVM Toolchain for MacOS

```bash
brew install llvm
```

</br>

### GNU Toolchain for Linux (Ubuntu) and WSL2

***x86***

```bash
./toolchains/scripts/i686-elf-tools.sh
```

***Arm32***

```bash
./toolchains/scripts/arm-none-eabi-tools.sh
```

</br>

### LLVM Toolchain for Linux (Ubuntu) and WSL2
```bash
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18
```

Learn more on <https://apt.llvm.org>

### Python Dependencies

It's recommended to use a virtual environment to avoid conflicts with system packages.

**Create and activate a virtual environment:**

```bash
# Create virtual environment
python3 -m venv venv

# Activate on Linux/macOS/WSL2
source venv/bin/activate
```

**Install dependencies:**

```bash
pip install -r utils/python_requirements.txt
```

**Note**: Remember to activate the virtual environment each time you work on the project. To deactivate, simply run `deactivate`.




## Building OS

Now we are ready to build the OS :)

### Generating Ninja

To generate ninja just run `./gn_gen.sh`. This command creates build directory `out/` and disk image for the OS.

***Note*** you can set some environment variables before running `./gn_gen.sh` to change some parameters, visit [Environment varibles](https://code.ayaantunio.me/ayaan/Custom-Operating-System/src/branch/master/docs/build.md#environment-variables) to learn more.

#### **Options of ./gn_gen.sh**

* --target_arch|--target_cpu(deprecated) *value*
  * Sets target arch.
  * Possible values:
    * x86 *(default)*
    * x86_64
    * arm32 / arm
    * arm64 / aarch64
* --host *value*
  * Sets toolchain to build the OS.
  * Possible values:
    * gnu *(default)*
    * llvm
* --device_type *value*
  * Configures OS parts to work in either desktop or mobile mode.
  * Possible values:
    * d / desktop *(default)*
    * m / mobile
* --test_method *value*
  * Possible values:
    * none *(default)*
    * tests
    * bench
* --target_board *value*
  * See "Available targets" table below.
* --dir *value*
  * Creates the build directory with the given name.
* -y|--yes
  * Force yes all operations.
* -h|--help
  * Prints all options of ./gn_gen.sh.

So to build xOS for Arm with LLVM you have to generate Ninja files with `./gn_gen.sh --target_arch arm32 --host llvm`

#### **Environment variables**

Another option how to configure the project is environment variables.

* `XOS_QEMU_SMP`
  * CPU cores count in the system.
* `XOS_QEMU_X86`
  * Path to *qemu-system-i386* executable
* `XOS_QEMU_X86_64`
  * Path to *qemu-system-x86_64* executable
* `XOS_QEMU_ARM`
  * Path to *qemu-system-arm* executable
* `XOS_QEMU_AA64`
  * Path to *qemu-system-aarch64* executable
* `LLVM_BIN_PATH`  *(Only with --host llvm)*
  * ***Must be set before `./gn_gen.sh`***
  * Path to LLVM bins.

</br>

### Building

Move to `out/` directory where the OS will be built. There are several scripts:

* `build.sh` - builds OS
* `sync.sh` - synchronise files with the disk image
* `run.sh` - launches QEMU or a real device

The right sequence to run the OS is to build, sync, launch or use `all.sh` which combine these 3 scripts.

**WSL2 Note**:  QEMU graphical output works on Windows 11 by default. On Windows 10, you may need to set `DISPLAY` environment variable if using an X server: 
```bash
export DISPLAY=:0
```

### Debugging

There are several scripts which might help you to debug the OS:

* `debug.sh` - launches QEMU in debug mode. Debug analog of `run.sh` (available only when run.sh uses QEMU)
* `dll.sh` - Debug analog of `all.sh`.

Also you can run `gdb` or `lldb` from the `out/` directory, which will automatically load kernel symbols and connect to QEMU in debug mode.

### Available boards

***x86***

* `i386` - regular x86 (i386). (default)

***x86_64***

* `x86_64` - regular x86_64. (default)

***Arm32***

* `vexpress-a15` - QEMU's vexpress-a15 target. (default)
