Add CMake file and code for post 4
This commit is contained in:
68
content/blog/04_compiler_improvements.md
Normal file
68
content/blog/04_compiler_improvements.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Compiling a Functional Language Using C++, Part 4 - Small Improvements
|
||||
date: 2019-08-06T14:26:38-07:00
|
||||
draft: true
|
||||
tags: ["C and C++", "Functional Languages", "Compilers"]
|
||||
---
|
||||
We've done quite a big push in the previous post. We defined
|
||||
type rules for our language, implemented unification,
|
||||
and then implemented unification to enforce these rules for
|
||||
our program. The post was pretty long, and even then we
|
||||
weren't able to fit quite everything into it.
|
||||
|
||||
For instance, we threw 0 whenever an error occured. This
|
||||
gives us no indication of what actually went wrong. We should
|
||||
probably define an exception class, one that can contain
|
||||
information about the error, and report it to the user.
|
||||
|
||||
Also, when there's no error, our compiler doesn't
|
||||
really tell us anything at all about the code besides
|
||||
the number of definitions. We probably want to see the types
|
||||
of these definitions, or at least some intermediate information.
|
||||
At the very least, we want to have the __ability__ to see
|
||||
this information.
|
||||
|
||||
Finally, we have no build system. We are creating more
|
||||
and more source files, and so far (unless you've taken
|
||||
initiative), we've been compiling them by hand. We want
|
||||
to only compile source files that have changed,
|
||||
and we want to have a standard definition of how to
|
||||
build our program.
|
||||
|
||||
### Setting up CMake
|
||||
This would be extremely easy if not for Flex and Bison. We start with the usual:
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 1 2 >}}
|
||||
|
||||
Next, we want to set up Flex and Bison. CMake provides two commands for this:
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 4 5 >}}
|
||||
|
||||
We now have access to commands that allow us to tell CMake about our parser
|
||||
and tokenizer (or scanner). We use them as follows:
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 6 12 >}}
|
||||
|
||||
We also want CMake to know that the scanner needs to parser's header file
|
||||
in order to compile. We add this dependency:
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 13 13 >}}
|
||||
|
||||
Finally, we add our source code to a CMake target. We use
|
||||
the `BISON_parser_OUTPUTS` and `FLEX_scanner_OUTPUTS` to
|
||||
pass in the source files generated by Flex and Bison.
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 15 22 >}}
|
||||
|
||||
Almost there! `parser.cpp` will be generated in the `build` directory
|
||||
during an out-of-source build, and so will `parser.hpp`. When building,
|
||||
`parser.cpp` will try to look for `ast.hpp`, and `main.cpp` will look for
|
||||
`parser.hpp`. We want them to be able to find each other, so we
|
||||
add both the source directory and the build (binary) directory to
|
||||
the list of includes directories:
|
||||
|
||||
{{< codelines "CMake" "compiler/04/CMakeLists.txt" 23 24 >}}
|
||||
|
||||
That's it for CMake! Let's try our build:
|
||||
```
|
||||
cmake -S . -B build
|
||||
cd build && make -j8
|
||||
```
|
||||
|
||||
We get an executable called `compiler`. Excellent! Here's the whole file:
|
||||
{{< codeblock "CMake" "compiler/04/CMakeLists.txt" >}}
|
||||
Reference in New Issue
Block a user