Sauce of Sunder: Setup and Installation
Welcome to the Sauce of Sunder, a series where we dive into the design and implementation of the Sunder programming language and associated tooling.
In this post, we are going to walk through the Sunder setup and installation procedure. By the time we are done, you should have a working Sunder toolchain installed on the platform of your choice, ready to begin Sunder development.
A Brief Bit of Background on Sunder's Supported Platforms
Sunder is a systems programming language that started life as a recreational research project in the early winter of 2021. In its original form, the Sunder compiler exclusively targeted x86-64 Linux, generating NASM-flavored assembly with its own custom ABI/calling convention, and interacting with the host system by making direct system calls to the Linux kernel. Although the Sunder of today is a lot more portable than the Sunder of the x86-64 Linux days, many of the design decisions from that period had a lasting impact on the design and implementation of the language which we still observe in the present.
One of those design decisions, relevant to us in this post, is the Unix-centric focus of the language, standard library, and tooling. You don't have to dig too deep to see that Sunder expects to operate within a Unixy world-model. In fact, the tagline for Sunder is literally "a modest systems programming language for Unix-like platforms". At the time of writing, Sunder works out of the box on x86-64 Linux, ARM64 Linux, ARM64 macOS, and on the web via WebAssembly through Emscripten's Unix-like abstraction layer, and could be ported to other common architectures and/or Unix-like platforms without too much hassle.
Crucially however, Sunder is not natively supported on the most popular desktop operating system, Windows. So for the rest of this post, and the rest of this series, we are going to assume that you, Dear Reader, will be interacting with the language and associated tooling on a supported Unix-like platform. For Linux and macOS users this probably just means "your computer", but for Windows users this means interacting with Sunder through either the Windows Subsystem for Linux or a virtual machine.
Diving Into Dependencies
Sunder is relatively lightweight in the dependencies required for installation and nominal operation. The Sunder compiler is written in clean C99, and generates GNU-flavored C11 as a "portable assembly" which is then handed off to a C compiler for backend compilation and linking. In addition to a GNU C compiler, you will need a standard set of POSIX development utilities to build the Sunder compiler and run the non-Sunder-compiler tools within the Sunder toolchain. And of course, you will need Git in order to actually clone the Sunder repository. Setup specifics for a handful of supported platforms are provided below. Follow along for your supported platform, and then move on to the next section.
Debian/Ubuntu
Run the following from the command line:
sudo apt update && sudo apt install build-essential git
Fedora
Run the following from the command line:
sudo dnf update && sudo dnf group install "Development Tools"
macOS
Run the following from the command line:
xcode-select --install
Building and Installing Sunder
Once you have all dependencies installed, the rest of the Sunder setup process is relatively straightforward. First, clone the Sunder repository using Git:
git clone https://github.com/ashn-dot-dev/sunder.git
Then cd
into the Sunder repository:
cd sunder/
From within the Sunder repository, build the compiler and install the Sunder toolchain:
make install
The install
target will install the Sunder toolchain into the directory
specified by the SUNDER_HOME
environment variable, which defaults to
$HOME/.sunder
. If you would like to install the Sunder toolchain into a
directory other than $HOME/.sunder
, specify a different SUNDER_HOME
when
running make install
:
make install SUNDER_HOME=/opt/sunder # Install to /opt/sunder
Then, after running the install
target, open up a text editor and add the
following blurb to your .profile
file located at ~/.profile
:
export SUNDER_HOME="$HOME/.sunder"
if [ -e "$SUNDER_HOME/env" ]; then
. "$SUNDER_HOME/env"
fi
If you used a SUNDER_HOME
location other than the default $HOME/.sunder
,
replace $HOME/.sunder
with your chosen SUNDER_HOME
location when editing
your .profile
. For example, if one had installed Sunder with make install SUNDER_HOME=/opt/sunder
, then they would add the following to their .profile
instead:
export SUNDER_HOME="/opt/sunder"
if [ -e "$SUNDER_HOME/env" ]; then
. "$SUNDER_HOME/env"
fi
After you have edited and saved your .profile
you should either restart your
computer so that the changes to your .profile
are picked up on login, or
source your .profile
within your current terminal session with:
. ~/.profile
If everything worked correctly, then you should be able to run sunder-compile -h
and see the Sunder compiler's help text. All together, the setup and
install process may look something like the following:
/tmp$ git clone https://github.com/ashn-dot-dev/sunder.git
Cloning into 'sunder'...
remote: Enumerating objects: 10488, done.
remote: Counting objects: 100% (307/307), done.
remote: Compressing objects: 100% (182/182), done.
remote: Total 10488 (delta 173), reused 208 (delta 115), pack-reused 10181 (from 3)
Receiving objects: 100% (10488/10488), 2.76 MiB | 13.03 MiB/s, done.
Resolving deltas: 100% (7042/7042), done.
/tmp$ cd sunder/
/tmp/sunder$ make install
c99 -o sunder-compile.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG sunder-compile.c
c99 -o util.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG util.c
c99 -o sunder.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG sunder.c
c99 -o lex.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG lex.c
c99 -o cst.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG cst.c
c99 -o parse.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG parse.c
c99 -o order.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG order.c
c99 -o ast.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG ast.c
c99 -o resolve.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG resolve.c
c99 -o eval.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG eval.c
c99 -o codegen.o -c -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG codegen.c
c99 -o bin/sunder-compile -DSUNDER_DEFAULT_ARCH=$(sh bin/sunder-platform arch) -DSUNDER_DEFAULT_HOST=$(sh bin/sunder-platform host) -DSUNDER_DEFAULT_CC=cc -DNDEBUG sunder-compile.o util.o sunder.o lex.o cst.o parse.o order.o ast.o resolve.o eval.o codegen.o
mkdir -p "$HOME/.sunder"
cp -r bin "$HOME/.sunder"
cp -r lib "$HOME/.sunder"
cp env "$HOME/.sunder"
/tmp/sunder$ vim ~/.profile # Update my .profile with SUNDER_HOME="$HOME/.sunder"
/tmp/sunder$ . ~/.profile
/tmp/sunder$ sunder-compile -h
Usage: sunder-compile [OPTION...] FILE
Options:
-c Compile and assemble, but do not link.
-d Do not invoke the C compiler to compile, assemble, or link.
-e Display the Sunder environment and exit.
-g Generate debug information in output files.
-k Keep intermediate files.
-L DIR Add DIR to the linker path.
-l OPT Pass OPT directly to the linker.
-o OUT Write output file to OUT (default a.out).
-h Display usage information and exit.
Testing Hello World
It would be a shame to go through all of this setup and installation without even getting to run a Sunder program, so before we conclude let's write our first Sunder program, which will print "Hello, world!" to the terminal.
Open up a new file, hello.sunder
, in your text editor of choice, and fill
that file with the following text:
import "std";
func main() void {
std::print_line(std::out(), "Hello, world!");
}
Then, from the command line, execute the following command:
sunder-run hello.sunder
The sunder-run
tool will automatically compile and execute simple Sunder
programs. In this case, sunder-run hello.sunder
will compile and execute our
hello world program, which should look like the following:
$ cat hello.sunder
import "std";
func main() void {
std::print_line(std::out(), "Hello, world!");
}
$ sunder-run hello.sunder
Hello, world!
Closing Thoughts
Congratulations on installing Sunder and running your first Sunder program! In future Sauce of Sunder posts we will use this installed Sunder toolchain to showcase the behavior of the Sunder language, standard library, compiler, and related tooling. Thank you for following along, and I will see you in the next installment of Sauce of Sunder.