Skip to content

Commit

Permalink
More updates for week 2
Browse files Browse the repository at this point in the history
  • Loading branch information
jdtournier committed Dec 18, 2024
1 parent 68ccaed commit b7aa730
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 9 deletions.
Binary file added images/compile_link.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions week1A.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,10 @@ To use the program, we need to _compile_ it

We do this by running the _compiler_ on our code:
```
$ g++ main.cpp
$ g++ -std=c++20 main.cpp
```
- the `-std=c++20` option instructs the compiler to use the C++20 version of the
C++ standard

--

Expand Down Expand Up @@ -583,7 +585,7 @@ By default, the compiler will produce an executable called `a.exe`
We can control the name of the executable using the `-o` [command-line
option](https://command-line-tutorial.readthedocs.io/introduction.html#command-line-options):
```
g++ main.cpp -o main
g++ -std=c++20 main.cpp -o main
```

--
Expand Down
10 changes: 5 additions & 5 deletions week1B.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ int main (int argc, char* argv[])

Compile with:
```
$ g++ shotgun.cpp -o shotgun
$ g++ -std=c++20 shotgun.cpp -o shotgun
```

---
Expand Down Expand Up @@ -316,7 +316,7 @@ The exit code is used to report success or failure to other programs
We can query the exit code of the last command in the terminal using the
special shell variable `$?` - for example:
```
$ g++ shotgun.cpp -o shotgun
$ g++ -std=c++20 shotgun.cpp -o shotgun
$ ./shotgun bogus.txt
ERROR: failed to open file "bogus.txt" - aborting
$ echo $?
Expand All @@ -336,7 +336,7 @@ the program we've just compiled.

We can do this very easily using [the `&&` operator](https://medium.frnn.dev/understanding-and-in-linux-bash-navigating-command-sequences-like-a-pro-fe5e72489da1):
```
$ g++ shotgun.cpp -o shotgun && ./shotgun bogus.txt
$ g++ -std=c++20 shotgun.cpp -o shotgun && ./shotgun bogus.txt
```

--
Expand Down Expand Up @@ -491,7 +491,7 @@ command-line](https://command-line-tutorial.readthedocs.io/paths.html)]

Putting it all together, we can write the full compile and run command as:
```
$ g++ shotgun.cpp -o shotgun && ./shotgun ../data/fragments-no-reverse-1.txt
$ g++ -std=c++20 shotgun.cpp -o shotgun && ./shotgun ../data/fragments-no-reverse-1.txt
```

--
Expand Down Expand Up @@ -772,7 +772,7 @@ Possible solution:
Now that we have code to load the data, we can run it and check that it works:

```
$ g++ shotgun.cpp -o shotgun && ./shotgun ../data/fragments-no-reverse-1.txt
$ g++ -std=c++20 shotgun.cpp -o shotgun && ./shotgun ../data/fragments-no-reverse-1.txt
reading fragments from file "../data/fragments-no-reverse-1.txt"...
read 190 fragments
```
Expand Down
279 changes: 277 additions & 2 deletions week2A.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
layout: presentation
title: "Week 2, session 1: multi-file projects, error handling
title: "Week 2, session 1: multi-file projects, error handling"
---

class: title
Expand Down Expand Up @@ -517,12 +517,13 @@ How do we compile this project?

We could compile everything in one go:
```
$ g++ shotgun.cpp fragments.cpp -o shotgun
$ g++ -std=c++20 shotgun.cpp fragments.cpp -o shotgun
```
--

That works, but it negates the benefits of incremental or parallel builds

--
What is normally done is:

- *compile* each `.cpp` file independently into an intermediate file format
Expand All @@ -538,3 +539,277 @@ What is normally done is:
readers can [read up on this
online](https://www.geeksforgeeks.org/static-and-dynamic-linking-in-operating-systems/))


---

# The compile & link process

![:right 65%](images/compile_link.png)



---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 -c shotgun.cpp -o shotgun.o
$ g++ -std=c++20 -c fragments.cpp -o fragments.o
```

Link:
```
$ g++ shotgun.o fragments.o -o shotgun
```

---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 `-c` shotgun.cpp -o shotgun.o
$ g++ -std=c++20 `-c` fragments.cpp -o fragments.o
```

Link:
```
$ g++ shotgun.o fragments.o -o shotgun
```

.explain-bottom[
The `-c` option instructs `g++` to *compile* only

<br>
Normally it would both compile *and* link
]



---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 -c shotgun.cpp -o `shotgun.o`
$ g++ -std=c++20 -c fragments.cpp -o `fragments.o`
```

Link:
```
$ g++ shotgun.o fragments.o -o shotgun
```

.explain-bottom[
Note that the output files from these commands are now *object files*, with the
`.o` extension
]


---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 -c shotgun.cpp -o shotgun.o
$ g++ -std=c++20 -c fragments.cpp -o fragments.o
```

Link:
```
$ g++ `shotgun.o fragments.o` -o shotgun
```

.explain-bottom[
The final link stage takes the object files only to produce the final
executable
]


---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 -c shotgun.cpp -o shotgun.o
$ g++ -std=c++20 -c fragments.cpp -o fragments.o
```

Link:
```
$ g++ shotgun.o fragments.o -o shotgun
```

Why bother when this could all be done with one command?

--

Because each of these tasks can be performed independently, and therefore in
parallel
- faster builds for large projects

--
and each of these tasks only needs to be performed if there has been a change
in its inputs
- e.g. if we edit `shotgun.cpp`, we do not need to re-compile `fragments.cpp`
- allows for *incremental builds* &ndash; can save huge amounts of time when
working on large projects


---

# Commands to perform the compile & link process

Compile:
```
$ g++ -std=c++20 -c shotgun.cpp -o shotgun.o
$ g++ -std=c++20 -c fragments.cpp -o fragments.o
```

Link:
```
$ g++ shotgun.o fragments.o -o shotgun
```

.explain-bottom[
Have a go at splitting up the code as shown previously, and compiling and
linking the different files using the commands above
]

---

# When do we need to recompile?

When we make changes to a file, it is not necessarily trivial to determine
which `.cpp` files need to be recompiled

--

If we edit `fragments.h`, we will need to recompile both `fragments.cpp` and
`shotgun.cpp`

--

If we edit `fragments.cpp`, we only need to recompile `fragments.cpp`
- `shotgun.cpp` does not include any part of `fragments.cpp`
- similarly for `shotgun.cpp`

--

The situation becomes much more complex for large projects
- a header file can `#include` other header files, which themselves can
`#include` other header files, etc.

--

To manage this web of dependencies, we use *C++ build systems* &ndash; of which
there are many...
- most well-known tools include `GNU make`, `cmake`, `qmake`, `ninja`, `meson`, `scons`, ...
- these can be very complex to understand and manage well
- some of these tools handle different aspects as well as building
- external dependencies, different operating systems, testing, packaging, ...

---

# How do C++ build systems work?

A comprehensive overview of C++ build systems is beyond the scope of this
course

--

At their most basic, build systems work by:
- knowing which *targets* depends on which inputs, e.g.:
- `shotgun.o` depends on `shotgun.cpp` & `fragments.h`
- `shotgun` depends on `shotgun.o` & `fragments.o`
--
- knowing which command to use to regenerate each *target* when necessary
- this could be an explicit command for each target, or a more generic *rule*
for each type of target
--
- establishing whether any of the dependencies have been modified more recently than
the *target*
- this is typically done via *timestamps*: the time of last modification
--
- if the *target* is older than any of its dependencies (or doesn't exist yet), then
it need to be regenerated

--

This needs to be done *recursively*:
- all dependencies of a target must themselves be up to date before working out
if the target needs to be regenerated
- e.g. both `shotgun.o` and `fragments.o` must be up to date
before deciding whether we need to relink them
- this can become quite messy in large projects...

---

# What build system is used in this course?


To keep things as simple as possible on this course, we will use a simple
script of our own design (the
[simple_build](https://github.com/jdtournier/simple_build) project)

On KCL systems, this script has already been made available as the command
`oop_build`

--

This script is capable of handling small projects, and does not require any
setting up or editing
- change directory (using `cd`) to your project folder, and run `oop_build`

--

The project must however follow some simple rules
- `cpp` files have the extension `.cpp`
- system headers are *all* `#include`d within angled brackets (`<>`)
- project headers are *all* `#include`d within inverted commas (`""`)
- any `cpp` file that contains a `main()` function will produce a matching
executable of the same name (minus the `.cpp` extension)
- any `cpp` file that needs to be compiled and linked into other executables
needs to have matching header of the same name, and this header needs to be
`#include`d in at least one other `cpp` file

--

If you follows the conventions taught on this course, the above rules
will always work for you

---

# Building our project using `oop_build`

Make sure your code has been split up as shown in this session
- or fetch the latest version from the website

The listing should show (at least) these files:
```
$ ls
fragments.cpp fragments.h shotgun.cpp
```

--

When ready, run the `oop_build` command and run the resulting executable:
```
$ oop_build
g++ -Wall -O2 -DNDEBUG -std=c++20 -I. -c shotgun.cpp -o shotgun.o
g++ -Wall -O2 -DNDEBUG -std=c++20 -I. -c fragments.cpp -o fragments.o
g++ shotgun.o fragments.o -o shotgun
```

--

You'll note there are more options in these commands than we've used so far
- you don't need to know about them &ndash; but if interested, feel free to look
them up online!



0 comments on commit b7aa730

Please sign in to comment.