# Compiler

Remember that we have to translate our source code to machine code, to do this, we need to install a *compiler*.

:::{wpd} compiler
a computer program that translates computer code written in one language into another language
:::

We will use `clang` compiler which is part of the [LLVM](https://llvm.org/) project.

## Installation

1. Go back to the terminal in your editor.
1. Install it using:
    
   ::::{tab-set}
   :::{tab-item} MacOS
   ```text
   brew install llvm
   ```
   :::
   :::{tab-item} Windows
   ```sh
   winget install martinstorsjo.llvm-mingw.ucrt
   ```
   :::
   ::::

1. Go back to your editor's terminal.
1. Check whether `clang` is installed and available in our environment by entering the following command in the terminal of the editor:

   ```
   clang
   ```
   You should see a message similar as follows:
   ```text
   clang: error: no input files
   ```

   :::{card} Troubleshooting
   If `clang` does not show the previous message and `clang` cannot be found, try the following in order:  

   1. Uninstall all LLVM installations using Windows `Add/Remove programs`.
   
      You can also use `winget`, but we have the impression that some packages which were installed with administrator rights fail to be uninstalled when you try with `winget` on a user terminal. Example `winget` command is:
   
      ```sh
      winget remove "LLVM MinGW (UCRT runtime)"
      ```
      
      After you have uninstalled all LLVM installations, install the compiler again:

      ```sh
      winget install martinstorsjo.llvm-mingw-ucrt
      ```
      
      Now close and open your editor and try to compile again. Otherwise try other steps:

   1. In this step, we will manually check whether `PATH` environment variable is correct. 
   
      First find where the compiler is installed. In Windows, the `martinstorsjo.llvm-mingw-ucrt` package installs the executables including `clang` under the following path:
   
      ```text
      C:\Users\YOUR_USERNAME\AppData\Local\Microsoft\WinGet\Packages\MartinStorsjo*\llvm-mingw-20*\bin
      ```
      Note the `YOUR_USERNAME` and `*` placeholders, so **do not copy paste** but click through the folder using the file explorer.

      The directory path ending with `bin` must be part of the *path* variable in your environment variables. To list and modify your path variable, refer to <project:#editing-the-environment-variable-path>.
   1. Probably you or your package manager modified your environment variable `path`, but the editor is not aware of this. Close **all** editor windows and restart your editor.
   :::

## Usage

Now compile `main.c` using the following command:

```
clang main.c
```

You should get no output, which means your source code is compiled to machine code binary `a.exe` on Windows and `a.out` in Linux. You should see it in the `EXPLORER` column.

:::{card} Troubleshooting
In Windows, if you get an error during compilation, check whether you have another version of LLVM installed in parallel, for example `llvm.llvm` in winget. You can list installed llvm packages using:

```sh
winget list llvm
```

If it exists, uninstall the package using its name, e.g.:

```sh
winget uninstall llvm.llvm
```

Alternatively you can also uninstall through `Add/remove programs`.
:::

(powershell-utf)=
## Configuring PowerShell for rendering special symbols

This is only required in Windows.

On Windows, PowerShell is the default terminal shell software. PowerShell uses a different decoding than the usual UTF so useful symbols like `çäæ😺` are not rendered correctly. To configure UTF support:

1. Start a PowerShell, e.g., using <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>`</kbd>
1. We will create a profile, which will be executed each time we open a PowerShell window. For security, Windows prohibits executing any scripts. To allow execution of local scripts execute the following on the shell:

   ```powershell
   Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
   ```
1. The following creates the folders for the profile file and adds the configuration for UTF output.

   ```powershell
   mkdir (Split-Path -Parent $PROFILE) -Force
   @"
   [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
   "@ >> $PROFILE
   ```
1. Now restart your editor or close all terminals in your editor.
1. You can check the setting using:

   ```powershell
   [Console]::OutputEncoding
   ```
   
   It should output:
   ```text
   BodyName          : utf-8
   EncodingName      : Unicode (UTF-8)
   ...
   ```

(running-your-program)=
## Running your program

On the same terminal, type the following to run your program:

::::{tab-set}
:::{tab-item} MacOS/Linux
```
./a.out
```
:::
:::{tab-item} Windows
```
./a.exe
```
:::
::::

We need to prefix our program with `./`, because your current directory (`.`) is not part of your `path` [by design](https://stackoverflow.com/a/6331085/13870816).

You should see the output `Hello!👋`.

:::{card} Troubleshooting
If you do not see `👋` on the terminal, check {ref}`powershell-utf`.
:::

## Creating and testing a task

Typing each time commands to the terminal to compile and run our program is not necessary. The editor features [tasks](https://code.visualstudio.com/docs/debugtest/tasks), which can use external programs. We will use tasks to compile our code – or *build* in general – within the editor and then to *run* our program.

1. Try to build your project using <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>b</kbd>. You should see `No build task ro run found. Configure Build Task...`.
1. Click on the last message. You should see `Create tasks.json file from template` and other menu items related to settings prefixed with the {{gear}} gear icon.
1. Select `Create tasks.json...`. You should see different tasks templates including `Others | Example to run an arbitrary external command`
1. Click on `Others ...`. `.vscode/tasks.json` will be created and opened in a new tab. The template defines a task called `echo`.
1. Let us try to run the created template. The task `echo` is not a build task right now, so it cannot be run using the build task.

   To run the build task we could use the traditional menu items on the top. Instead, we will use the *command palette*, which makes it possible to search for a menu item.

   Press <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>p</kbd>. The command **p**alette window should pop up.
1. Type `run task` and then select `Tasks: Run Task`. The window will show many tasks including `echo`.
1. Select `echo`. A new window will show up with `Select for which kind of errors ... to scan the task output`.
  
   Scanning the output is helpful, e.g. for:
   1. directly jumping to the error in our source code. 
   1. to have an overview of issues in our code on the `PROBLEMS` tab (left to the `TERMINAL` tab).

   We are not going to use this feature, as we will directly get feedback about our program syntax mistakes on our editor window through the language server `clangd` that we will install later.
   
1. Click on `Continue without scanning the task output`. A new terminal window prefixed with 🛠️ echo should be opened and it will output `Hello`. 

   `Hello` comes from the shell command `echo Hello`.

   If you don't get the message, check whether you named your `tasks.json` correctly. I once named it `task.json`, which was not easy to spot.

:::{figure} ../img/example-of-cluttered-project-directory.png
:name: example-of-cluttered-project-directory
:align: right
:figwidth: 40%
An example of a cluttered documentation project (not C). Here, Markdown (`*.md`) files are the files I focus on when writing the course materials. Finding an `*.md` file under `week02` is much more convenient than in the bottom where other files are blended in like `*.py`, `*.sh`, `Makefile` etc. Introducing a `src` folder would separate `*.md` files.
:::

## Organizing source files under `src`

Create a new folder called `src` in your project folder and move `main.c` in `src` folder. From this point on we will put the `*.c` files in there.

But why? In projects where we have only a single source file, this creates unnecessary directory complexity, so it may seem needless at first. We will introduce later other files like `README.md`, `compile_flags.txt` and even other source files (`*.c`) and header files (`*.h`) later. We don't want the mix these files we will mostly use with other *meta* files, because working with in a project with many source files will be cumbersome as shown in {numref}`Figure %s <example-of-cluttered-project-directory>`.
    
A project has usually *meta* files, which are not exactly project contents (in other words source files) but files *about the project*, e.g., project settings, README, compiler settings, license etc. So we should separate meta files from source files in a project with several files.


## Setting up tasks for compiling & running our code using clang

`echo Hello` in our current `tasks.json` does not compile and run our program. For compiling and running we have to tweak `tasks.json`.

We will set up two different tasks: `build` and `run`

1. Change the `tasks.json` as follows:
   
   :::{literalinclude} ../c-template/.vscode/tasks.json
   :language: json
   :::

   What is going on above?
   - We separated the compiler command from the arguments using `args` in addition.
     - We need additional arguments to the compiler. Instead of writing all arguments in `args`, we will introduce `compile_flags.txt`. `@` means that the following argument contains the file where the compiler flags will be read from.
     
       `'` single quotation marks are required to escape `@` symbol in PowerShell, because [`@` has a special meaning](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting).
     
      The main reason for `compile_flags.txt` is the language server *clangd* we will introduce later. Clangd can only read its arguments from `compile_flags.txt`. We will have the compiler arguments for clang and clangd in one file.
     - We use `-o main` which sets our program's name to `main` instead of `./a.(out|exe)`.
   - in the `run` task, we use `dependsOn`, so that running the `run` task always builds the project first.
   - we set `build` as a build task, and `run` as a test task, because, they are handled differently in VS Code. Moreover we set both tasks as default tasks in their group, which saves an additional click when we want to run these tasks.
   
1. {#compile_flags}
   Now save `tasks.json` and create `compile_flags.txt` with the following content:
   
   :::{literalinclude} ../c-template/compile_flags.txt
   :language: text
   :::
   
   In this file we use:
   - `-std` option to clang, which stands for C *standard*.
   
     Clang uses and older but stable C standard called `gnu17` as default. We want to try the [latest C features](https://clang.llvm.org/c_status.html) in this course – hence the the option.
   - Added `-g` option, which generates additional information which can be useful in a debugging session


1. Run the `run` task by opening the command pallette (shortcut contains <kbd>p</kbd>) and searching for `test task`. After running you should get an output similar to in the `Terminal`:

   ```text
    *  Executing task: clang @compile_flags.txt main.c -o main
   ... 
   ```

:::{tip}
The build task automatically saves your project files before running the task. Don't lose time with saving your source files before executing the task.
:::

## Appendix

- [Integrate with external tools via tasks](https://code.visualstudio.com/docs/debugtest/tasks)
- 
  :::::{dropdown} clangd automatically compiles the project and populates `Problems` tab, so there is no need for `problemMatcher` in `tasks.json`. Currently I don't see any purpose for it, but in case there is, you can set it up as follows:

  ::::{tab-set}
  :::{tab-item} VSCodium
  ```json
  "label": "build",
  // ...
  "problemMatcher": {
      "pattern": {
          "regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
      }
  },
  ```
  :::
  :::{tab-item} VS Code
  A problem matcher is built-in:
  ```json
  "label": "build",
  // ...
  "problemMatcher": ["$gcc"],
  ```
  :::
  ::::
  :::::
- 
  :::{dropdown} `tasks.json` also supports [OS specific properties](https://code.visualstudio.com/docs/debugtest/tasks#_operating-system-specific-properties). If you work in a project group or on multiple OSs, you can use the `windows`, `osx`, `linux`:

  ```json
  {
   "tasks": [
       {
           "label": "run",
           "type": "shell",
           "group": {
               "kind": "test",
               "isDefault": true
           },
           "windows": {
               "command": "./a.exe"
           },
           "osx": {
               "command": "./a.out"
           },
           "linux": {
               "command": "./a.out"
           },
           "dependsOn": [
               "build"
           ],
       },
   ],
   "version": "2.0.0",
  }
  ```
  :::
  
:::{spelling}
alette
txt
:::