A bit of inspiration for building YOUR Platform.

envsetup.sh -- a very useful automation technique

Cliff Brake January 10, 2025 #automation #shell

During a Android development stint, I learned about the envsetup.sh concept. This is a script that contains numerous functions get populated in a shell envrionment when the script is sourced. There two ways to source the file -- you can type:

source envsetup.sh

Or use a '.' for a shortcut for source and type:

. envsetup.sh

Most of my projects and Git repos now contain a envsetup.sh file (examples: Simple IoT, Yoe, TMPDIR Podcast). Typically all of the functions in the file have a common prefix. This gives them a namespace and allows you to see all the functions quickly in your terminal by typing <prefix><tab><tab>.

Why shell functions instead of something like Make, Earthly, Nix, Task, Mage, Pants, Bazel, Python ...? Shell script is about the simplest abstraction on top of typing commands. Thus, if mostly what you need to do is execute a sequence of terminal commands, then shell functions are very efficient at doing this. A shell function is often the best documentation for how to do something -- it is almost like a powerful checklist. There are no dependencies -- every Linux and MacOS system comes with a shell built-in. envsetup.sh functions can often be used directly in CI/CD and other build systems (like Yocto/Bitbake tasks).

There are some common objections ...

Shell is not cross-platform to Windows. That is unfortunate, but I rarely use Windows, and most developers I interact with use either Linux or MacOS systems. However, this may change with Zephyr as MCU developers traditionally have used Windows.

Why not use something more powerful like Make? With modern programming languages and build systems like Go, Rust, and Yocto, the is no need for yet another build system. The complex issues like dependencies are already handled. Thus, all you need to do is remember how to kick it off.

Why not use Python -- everyone uses Python for everything -- it is the most popular programming language ever! Python is great if you need to do something more complex, but it is a more complex programming abstraction. And mostly what you need to do is record a sequence of commands, any abstraction costs you more than benefits.

Why not a shell script that you execute instead of sourcing a script that populates functions? I'm not sure -- the sourcing just seems more ergonomic to me and simpler. If you need to run a script to execute a command, then you need to process command line arguments, etc. You are now programming, and programming is what we are trying to avoid in envsetup.sh. Also, the functions are not as discoverable as when they are populated in your environment.

Shell scripting is not without its tradeoffs -- when you do need to program something in shell, it can be very painful and errors can be subtle and hard to catch. However, AI tools are very effective at writing shell script, so this can be a big help. Linters and formatters are also very good at catching problems early and making your scripts more readable (more on this later).

In summary, think of your envsetup.sh file primarily as documentation. Create one in every project and instead of documentation how to do something, create a shell function. Your future self will thank you.