Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/nerves systems guide improvement #1032

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 128 additions & 22 deletions guides/advanced/building-sytems.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,29 @@ The `nerves_systems` build process only works on **Linux** systems with `x86_64`

Install the following packages in your Linux environment:

#### Apt based distributions (Ubuntu, Debian...)
```bash
sudo apt update && sudo apt install -y git build-essential bc cmake cvs wget curl mercurial python3 python3-aiohttp python3-flake8 python3-ijson python3-nose2 python3-pexpect python3-pip python3-requests rsync subversion unzip gawk jq squashfs-tools libssl-dev automake autoconf libncurses5-dev
```

> #### Compatibility Note {: .info}
>
> This command is compatible with Debian 11 and 12, and Ubuntu 20.04, 22.04. Older distributions may require adjustments.

Comment on lines +33 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> #### Compatibility Note {: .info}
>
> This command is compatible with Debian 11 and 12, and Ubuntu 20.04, 22.04. Older distributions may require adjustments.

I think the compatibility note is implied now that you added Arch and Fedora and can be deleted to make the text shorter.

#### Arch linux
```bash
sudo pacman -Syu git base-devel bc cmake cvs wget curl mercurial python python-aiohttp flake8 python-ijson python-nose2 python-pexpect python-pip python-requests rsync subversion unzip gawk jq squashfs-tools openssl automake autoconf ncurses
```

#### RPM based distributions (Red Hat, Fedora...)
```bash
sudo dnf install -y git gcc gcc-c++ make bc cmake cvs wget curl mercurial python3 python3-aiohttp python3-flake8 python3-ijson python3-nose2 python3-pexpect python3-pip python3-requests rsync subversion unzip gawk jq squashfs-tools openssl-devel automake autoconf ncurses-devel
```

> #### Why These Packages? {: .info}
>
> These packages provide essential tools and libraries required for the Buildroot environment and system customization.

> #### Compatibility Note {: .info}
>
> This command is compatible with Debian 11 and 12, and Ubuntu 20.04, 22.04. Older distributions may require adjustments.

### macOS Setup

Expand Down Expand Up @@ -277,34 +289,70 @@ Customizing your Nerves system is an advanced but powerful way to tailor the sys

Customizing the build allows you to tailor the Nerves system to meet specific requirements for your hardware or application. This involves modifying Buildroot configurations and applying changes to the Nerves system.

### Modify Buildroot Configuration
### Modify Buildroot Package Configuration

Nerves systems use Buildroot for building firmware. The `make menuconfig` command opens a menu-based interface where you can modify the Buildroot configuration:
Navigate to the output directory of system you wish to modify.

```bash
cd o/<system short name>
make menuconfig
```

In this interface, you can:
Workflow for customizing a Nerves system is the same as when using Buildroot outside of Nerves,
using `make menuconfig` and `make savedefconfig`.

- Add or remove packages.
- Configure kernel options.
- Set custom build flags.
The main package configuration workflows are divided into three categories,
depending on what you want to configure:

> #### Tip {: .tip}
>
> Only make changes you understand, as incorrect settings may cause build failures or unstable firmware. For more details on Buildroot configuration, refer to the [Buildroot user manual](https://buildroot.org/downloads/manual/manual.html).
1. Select base packages by running `make menuconfig`
2. Modify the Linux kernel and kernel modules with `make linux-menuconfig`
3. Enable more command line utilities using `make busybox-menuconfig`

### Save the Updated Configuration
When you quit from the `menuconfig` interface, the changes are stored
temporarily. To save them back to your system source directory, follow the
appropriate steps below:

After making changes in `menuconfig`, save the configuration back to the system’s default configuration file (`nerves_defconfig`) using:
1. After `make menuconfig`:

```bash
make savedefconfig
```
Run `make savedefconfig` to update the `nerves_defconfig` in your System.

2. After `make linux-menuconfig`:

Once done with configuring the kernel, you can save the Linux config to the
default configuration file using `make linux-update-defconfig`. The destination
file is `linux-4.9.defconfig` in your project's root (or whatever the kernel
version is you're working with).

> NOTE: If your system doesn't contain a custom Linux configuration yet,
you'll need to update the Buildroot configuration (using `make menuconfig`)
to point to the new Linux defconfig in your system directory. The path is
usually something like `$(NERVES_DEFCONFIG_DIR)/linux-x.y_defconfig`.

3. After `make busybox-menuconfig`:

Unfortunately, there's not currently an easy way to save a BusyBox defconfig.
What you have to do instead is save the full BusyBox config and configure it
to be included in your `nerves_defconfig`.

```bash
cp build/busybox-1.27.2/.config ../src/<full system name>/busybox_defconfig
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using <full system name> here is not ideal.

Likely scenario is that you would want to add new system to config.exs
run

mix ns.clone
# Then actually just populate o directory with something like
mix ns.build --configure
# where it would just create o directory with config without building it

Ideally that would provide us with shell script that could export NERVES_DEFCONFIG_DIR
then this could be.

cp build/busybox-1.27.2/.config ${NERVES_DEFCONFIG_DIR}/busybox_defconfig

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also be good idea for build to accept --only

mix ns.build --only custom_rpi3

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed this, but the line:

cp build/busybox-1.27.2/.config ${NERVES_DEFCONFIG_DIR}/busybox_defconfig

should be

make busybox-update-config

This takes care of copying the Busybox config to the right place and will properly error out if the fragment config feature is being used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I tried this with rpi3 system and

make busybox-update-config

results in

cp -f /home/damir/Projects/nerves/nerves_systems/o/rpi3/build/busybox-1.36.1/.config /home/damir/Projects/nerves/nerves_systems/src/nerves_system_br/board/nerves-common/busybox.config

Which now applies it to all other systems which is IMO not wanted behavior.

In case when fragments are set it does error

Unable to perform busybox-update-config when fragment files are set
make[1]: *** [package/busybox/busybox.mk:464: busybox-update-config] Error 1
make: *** [Makefile:23: _all] Error 2

How this guide states it in current version would be correct for using fragments.

I guess my question is what would be correct way to automate

cp build/busybox-1.27.2/.config ../src/<full system name>/busybox_defconfig

Maybe add new make option `make busybox-update-fragment-config that would basically call

cp build/busybox-1.27.2/.config ${NERVES_DEFCONFIG_DIR}/busybox_defconfig

and maybe set fragments at the same time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you're right, if you have never modified the busybox.config then it goes to the default one.

I'd do this:

cp build/busybox-1.27.2/.config ../src/<full system name>/busybox.config

Then run make menuconfig to set BR2_PACKAGE_BUSYBOX_CONFIG to ${NERVES_DEFCONFIG_DIR}/busybox.config, and then make savedefconfig.

Then when I wanted to update it in the future, make busybox-update-config will work.

Side note: Busybox only knows how to save .config files. Linux and Buildroot can save .config and _defconfig versions where the defconfig version only has the nondefault settings.

```

Like the Linux configuration, the Buildroot configuration will need to be
updated to point to the custom config if it isn't already. This can be done
via `make menuconfig` and navigating to **Target Packages** and finding the
**Additional BusyBox configuration fragment files** option under the
**BusyBox** package, which should already be enabled and already have a base
configuration specified. If you're following along with this example, the
correct configuration value should look like this:

```bash
${NERVES_DEFCONFIG_DIR}/busybox_defconfig
```

The [Buildroot user manual](http://nightly.buildroot.org/manual.html) can be
very helpful, especially if you need to add a package. The various Nerves system
repositories have examples of many common use cases, so check them out as well.

This ensures that your changes are preserved in the Buildroot configuration and can be reused in future builds. Learn more about Nerves system configuration in the [Nerves documentation](https://hexdocs.pm/nerves/systems.html).

### Rebuild the System

Expand All @@ -321,7 +369,6 @@ This ensures a fresh build with your updated configuration.

You can further customize the Nerves system by modifying other configuration files, such as:

- **Linux kernel configuration:** Located in the Buildroot environment.
- **System files:** Add or update scripts, binaries, or other files required by your application.

To dive deeper into kernel customization, see the [Linux Kernel Documentation](https://www.kernel.org/doc/html/latest/).
Expand All @@ -341,8 +388,67 @@ If your customizations are for long-term use, consider committing your changes t
- Reproducing builds in the future.

Example:
Let's say that you want to version control your customized rpi3 system

```bash
cd src
cp -r nerves_system_rpi3 custom_rpi3
```

The name of the system directory is up to you, but we will call it `custom_rpi3`
in this example. It's recommended that you check your custom system into your
version control system before making changes. This makes it easier to merge in
upstream changes from the official systems later. For example, assuming you're
using GitHub:


```bash
git add config/nerves_defconfig
git commit -m "Customize Buildroot configuration for <system name>"
# After creating an empty custom_rpi3 repository in your GitHub account

cd custom_rpi3
git remote rename origin upstream
git remote add origin git@github.com:YourGitHubUserName/custom_rpi3.git
git checkout -b main
git push origin main
```


Next, tweak the metadata of your Mix project by updating your `mix.exs` with the following:

* The module name of the mix project at the top of the file
* the value of `@app` to `custom_rpi3`
* the value of `@github_organization` to your GitHub user name or organization

See the [Official Mix.Project](https://hexdocs.pm/mix/Mix.Project.html) document
for the structure of this file.

```elixir
# custom_rpi3/mix.exs

# defmodule NervesSystemRpi3.MixProject do
defmodule CustomRpi3.MixProject do
# =^^^^^^^^^^= Rename `NervesSystemRpi3` to `CustomRpi3`
use Mix.Project

# @github_organization "nerves-project"
@github_organization "YourGitHubUserOrOrganizationName"
# =^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^=
# Rename `"nerves-project"` here to your GitHub user or organization name

# @app :nerves_system_rpi3
@app :custom_rpi3
# =^^^^^^^^^^^= Rename `nerves_system_rpi3` here to `custom_rpi3`
end

# =^^^= The rest of this file remains the same
```

```bash
# Commit and push your changes.

git add mix.exs
git commit -m "Change project info"
git push
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
git push
git push origin main

```

Now you can go to your `nerves_systems/config/config.exs` and add it to your systems.
Copy link
Author

@Damirados Damirados Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should include another section of how to now add custom system in a project and use it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.