# Extensions

> "I'm gonna create a `prepare_bootloader` hook [in core] so we can refactor `u-boot` [into an extension]"

The extensions framework allows the board/family developers, extension authors, and users to extend the Armbian build system without overloading the core with specific functionality.

It's a simple framework, written in Bash, that **works based on function naming conventions**. It provides the core and the extensions with tracing and debugging, (error control,?) inline documentation and very simple dependency resolution.

### Terminology
- The "core" is everything that's in `lib/` directory plus `compile.sh` and some others. It's the spine of the build system.
- An "extension" is a separate Bash source file that contains exclusively functions. Extensions live in `extensions/` or `userpatches/extensions/` directory, but could one day be in a separate repository too.
- An "extension method" (a.k.a "hook") is used by the core to call extensions, via `call_extension_method()`. This will discover all enabled extension methods implementations, order them, and call them one by one.
    - The Armbian core already has quite a few of these in strategic spots.
    - More are coming as they're identified.
- An "extension method implementation" is a function that will be called when it's extension method is called. It can be defined in extensions, but also in board config, family config, user config, etc.

#### Example

##### Core calls extensions

The Armbian core build system has an extension method called `run_after_build`, also known as the "`run_after_build` hook". You can find it in `lib/main.sh` around line 546.

```bash
# in lib/main.sh:546
call_extension_method "run_after_build" [...]
```


##### Extension method implementation

Consider the following function:

```bash
function run_after_build__say_congratulations() { 
  echo "Congrats, the build is finished!"
}
```

Such a function is an "extension method implementation" called `say_congratulations` for the extension method `run_after_build`.

##### Extension file

A file `userpatches/extensions/be-festive.sh` containing the above function is an "extension" called `be-festive`.

##### Using it

An user of the build system can enable that extension by adding a call to `enable_extension "be-festive"` on his configuration file, or by passing `ENABLE_EXTENSIONS=be-festive` as a parameter to the build.


### Naming conventions and ordering

An extension method implementation is just a Bash function that follows the pattern `run_after_build__say_congratulations` where

- `run_after_build` is the name of the extension method.
- `__` is a marker/separator -- very important -- two underscores, not one, not three.
- `say_congratulations` is the name of the extension method implementation, and should be unique.

The system will "magically" compose a single `run_after_build()` function, based on all the hook functions that begin with `run_after_build__`.

Hook functions will be sorted by their numerical value; hook functions that do not begin with a number will receive `500_` prefix automatically.

So the examples `run_after_build__do_this` and `run_after_build__500_do_this` are equivalent, and will run

- sooner than `run_after_build__900_do_smth_else`
- later than `run_after_build__300_do_even_another_thing`



### What is an _extension_?

A extension is Bash source file that contains **exclusively**:

- function definitions:
    - extension method implementation definitions (with `__` separator)
    - other internal functions (for structure and clarity if needed)
- calls to `enable_extension "another-extension"` at the top of the file.
    - that's a very simple dependency system, one extension can enable another.

Specifically, **extension files should not contain any code outside of functions** -- they should do nothing when sourced.

Extensions can be official Armbian fragments and live in `/extensions`, or can be user-specific
in `/userpatches/extensions`.

An extension could be implemented in any of the following file/dir structures:

- `/extensions/our-ext.sh` - an official, single-file extension.
- `/userpatches/extensions/my-ext.sh` - a user-specific, single-file extension.
- `/extensions/our-dir-ext/our-dir-ext.sh` - an official, directory-based extension.
- `/userpatches/extensions/my-dir-ext/my-dir-ext.sh` - a user-specific, directory-based extensions.

The official extensions can be used by boards, family includes, etc, while the user-specific extensions can only be used by userpatches code or via `ENABLE_EXTENSIONS=my-ext,my-dir-ext` build parameter.

#### Single-file vs Directory-based

They're the same, except:

- Directory-based extensions will be passed a `${EXTENSION_DIR}` environment variable.
- That is useful if there are other files/assets that belong together with that extension. An example would be a template file, some configuration file, or other static asset that is directly related to the extension.
- Using directory-based extensions and `${EXTENSION_DIR}` allows for easy moving and PR'ing of user extensions.
