To recap, to write suru I had to: Write a parser in a Parser Expression Grammer to parse taskfiles. Generate a build graph listing the dependency roots and their dependents. Execute the build graph in a multithreaded manner. All in all, writing Suru only took 4 days of work, and only a couple hundred of lines of code. I enjoyed how Rust combines bits of C++ and Haskell into a cohesive language that offers the elegance of Haskell and the versatility of C++....
The making of Suru part 3: Multitasking
The second part of building Suru is constructing a build graph. A build graph is almost certainly necessary in the context of multithreading because of the presence of diamond dependencies. Constructing a graph in Rust isn’t too bad, but does require a little big of fandangling. Rc, Arc, Refcell, Mutex, RwLock??? I’ve seen some people get confused between the various constructs Rust has surrounding multithreading, but if you have a context in C++ multithreading it’s not very complicated....
The making of Suru part 2: Parsing
The first part of building suru was creating a parser, which was the part with the most false starts. The syntax I had in mind was relatively poorly defined at the time. Unfortunately, this lead to me a parser only to find out that it wouldn’t inherently work. Nom I literally searched up parsers on lib.rs, and the first result I found was nom. Nom is a combinator parsing library intended for parsing binary formats, but also was serviceable for parsing text....
Suru
I’ve made a build tool to replace make. It’s intended to be very similar to make, but with modern features that make lacks. Check it out on crates.io! Basic usage Make a file called tasks.su. Write the following in your taskfile. a.out: main.o % < *.o g++ $^ -o $@ Make sure the indentation is made with a hard tab. The syntax is very similar to Make, but unlike Make, pattern rules are separated from normal build rules....
The making of Suru part 1: Scope
For a long time, I wanted to make a makefile replacement. Writing a good makefile is surprisingly non-trivial if you want certain features. For example, the internal pattern rules of make fail if you want to do an out of tree build, which is most modern builds. Moreover, making sure that make does not fail when a dependent header file is surprisingly obscure. Even to this day, the best makefile template is very much a matter of debate....
Exceptions Explained Part 4: C++
After quite the lengthy tread through GCC and C-land (mind you everything discussed before was written in C), we finally find ourselves back at C++. C++ exception semantics seem simple, but actually hide many surprising edge cases. Functions Like before, let’s discuss the API of the C++ exception handling regime. Note that while you’re not supposed to call these functions directly, these functions are called in compiler generated code anyways, so are a part of the public ABI....
Exceptions Explained Part 3: libunwind
Last time I mentioned libunwind, but now I’m going to go over the implementation of libunwind in GCC. As mentioned before, libunwind used to be a library developed by HP, but it got vendored into GCC as a part of libgcc. libgcc itself is a small library containing, besides libunwind, various intrinsics for floating point and integer math. libunwind One might reasonably ask the question of how one can unwind a stack while using functions that modify the stack?...
Exceptions Explained Part 2: Frame Information
Last time I talked about the broad architecture of how exceptions work. Today I’m focusing on how debug information is contained in the eh_frame section. To explain why exception information is held in the format it is today, we need to dive a little into the history of libunwind. Much of what is here comes from linux reference documents, found here. History Libunwind was originally developed by HP back in the days of the unix wars....
Exceptions Explained Part 1: Architecture
As it turns out there’s not really a good in depth explanation of how exceptions work. There are disparate explanations of how separate parts of exceptions in C++ work, but not really the whole picture. So I’m writing this down here as a reference to how everything in C++ exceptions work. Disclaimer My experiences are exclusively in GCC. Broadly, Clang should follow the same Architecture as GCC, but may vary in implementation details....
BLDC Driver
I got very bored and decided to create a brushless DC motor driver pcb. It was pretty fun going through all of the design considerations, so here we go. Architecture The BLDC driver is intended to be run by a MicroMod controller. This is mostly because the club I’m at uses MicroMods extensively, and I wanted to put this in that same ecosystem. Despite what the schematic implies, power does actually come from the power section, it’s just that power symbols in KiCad are global and don’t show up on hierarchal schematics....