Skip to content

Commit 3bc7bb8

Browse files
committed
ch01: Greatly simplifying chapter one
References to vcpkg are no longer present in published book as I want to focus on CMake only builds as I package managers are non-standard and highly opinionated. FetchContent will suffice for the simple package management examples that ch06 will feature. The description of CMake presets has also been removed. While they are useful and I prefer using them for configuring things like compiler flags, cache variables etc. over directly in CMakeLists.txt files, they require and additional file to be created and managed by readers and I wanted to keep the opening chapter as concise as possible to allow for the reader to move quickly to chapters 02 and 03. To compensate a more complex CMake config will be covered in an appendix page with some in-between content being featured in ch06 when discussing larger project structures. The whichlang JS and CSS files have been added to allow codeblocks to be rendered in a more decorative manner. This was added to help codeblocks; particularly for shell commands across platforms, to be more distinguishable between each other. While PowerShell and Command Prompt do not have icons due to a transient dependency; Simple Icons, not having any the 'filepath' option allows for a text indication of which shell a command is for.
1 parent eebe33a commit 3bc7bb8

17 files changed

Lines changed: 13418 additions & 201 deletions

File tree

book.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ src = "src"
1111
[output.html]
1212
mathjax-support = true
1313
git-repository-url = "https://github.com/oraqlle/cpp-book"
14-
additional-css = ["./mdbook-admonish.css"]
14+
additional-css = ["./mdbook-admonish.css", "./whichlang.css"]
15+
additional-js = ["./whichlang.js"]
16+
hash-files = true
1517

1618
[output.html.playground]
1719
editable = true

src/SUMMARY.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
- [MacOS](ch01-getting-started/macos.md)
1313
- ["Hello, World!"](ch01-getting-started/hello-world.md)
1414
- ["Hello, CMake!"](ch01-getting-started/hello-cmake.md)
15-
- ["Hello, vcpkg!"](ch01-getting-started/hello-vcpkg.md)
1615
- ["Hello, Godbolt!"](ch01-getting-started/hello-godbolt.md)
1716

17+
<!-- ["Hello, vcpkg!"](ch01-getting-started/hello-vcpkg.md) -->
18+
1819
## Sample Project
1920

2021
- [Project: Guessing Game](ch02-guessing-game/guessing-game.md)
@@ -72,7 +73,7 @@
7273
<!-- - [Access Modifiers](custom-types/access-modifiers.md) -->
7374
<!-- - [Constructors, Destructors and RAII](custom-types/raii.md) -->
7475

75-
## Managing Growing Projects
76+
## Larger Projects
7677

7778
<!-- - [Managing Growing Projects](managing-projects/managing-projects.md) -->
7879
<!-- - [Namespaces](managing-projects/namespaces.md) -->
@@ -196,8 +197,9 @@
196197
- [Appendix](appendix/appendix.md)
197198
- [A - Keywords](appendix/A-keywords.md)
198199
- [B - Operators](appendix/B-operators.md)
200+
- [C - Standard Versions](appendix/C-standard-versions.md)
201+
- [D - Recommended Compiler Flags](appendix/D-cxx-flags.md)
199202
<!-- - [C - Developer Tools](appendix/devtools.md) -->
200-
<!-- - [D - Standard Versions](appendix/standard-versions.md) -->
201203
<!-- - [E - Value Categories](appendix/value-categories.md) -->
202204
<!-- - [F - Compiler Vendors](appendix/compiler-vendors.md) -->
203205
<!-- - [G - Compilation Pipeline](appendix/compilation-pipeline.md) -->
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# C - Standard Versions
2+
3+
```admonish warning
4+
🚧 Page Under Construction! 🏗️
5+
```

src/appendix/D-cxx-flags.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# D - Recommended Compiler Flags
2+
3+
```admonish warning
4+
🚧 Page Under Construction! 🏗️
5+
```

src/ch01-getting-started/examples/hello_cmake/CMakeLists.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/ch01-getting-started/examples/hello_cmake/CMakePresets.json

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/ch01-getting-started/examples/hello_cmake/main.cxx

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cmake_minimum_required(VERSION 3.22)
2+
3+
project(hello_world
4+
VERSION 0.1.0
5+
DESCRIPTION "Hello, CMake!"
6+
LANGUAGES CXX)
7+
8+
add_executable(hello_world main.cxx)
9+
target_compile_features(hello_world PRIVATE cxx_std_17)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
cmake_minimum_required(VERSION 3.22)
2+
3+
project(hello_world
4+
VERSION 0.1.0
5+
DESCRIPTION "Hello, CMake!"
6+
LANGUAGES CXX)
7+
8+
add_executable(hello_world main.cxx)
9+
target_compile_features(hello_world PRIVATE cxx_std_17)
10+
11+
if (MSVC)
12+
# warning level 4
13+
add_compile_options(/W4)
14+
else()
15+
# additional warnings
16+
add_compile_options(-Wall -Wextra -Werror -Wpedantic)
17+
endif()

src/ch01-getting-started/hello-cmake.md

Lines changed: 56 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -8,129 +8,85 @@ testing. This allows a single project to build many different outputs for differ
88
platforms from a single source. Targets can also be consumed by other targets allowing
99
more modular builds.
1010

11-
## Creating a Project with CMake
11+
## Adapting our hello_world Project
1212

13-
To start off, go back to your `projects/` directory and create a new directory called
14-
'hello_cmake'.
13+
To start off, go back to your `projects/hello_world` directory and create a new file
14+
`CMakeLists.txt`.
1515

16-
```sh
17-
$ mkdir hello_cmake
18-
$ cd hello_cmake
16+
```sh,icon=%gnubash,fp=Shell
17+
$ cd ~/projects/hello_world
18+
$ touch CMakeLists.txt
1919
```
2020

21-
Within this directory we will need to create three new files `main.cxx`, `CMakeLists.txt`
22-
and `CMakePresets.json`. For the `main.cxx` file you can copy the below code which is
23-
identical to the one found on the previous page except printing slightly different
24-
content.
25-
26-
```cpp
27-
{{#include examples/hello_cmake/main.cxx}}
21+
```haskell,icon=,fp=PowerShell
22+
Set-Location projects/hello_world
23+
New-Item -Path . -Name "CMakeLists.txt" -ItemType "File"
2824
```
2925

30-
We will first look at the `CMakeLists.txt` file.
26+
```haskell,icon=,fp=CommandPrompt
27+
> cd ~/projects/hello_world
28+
> echo. > CMakeLists.txt
29+
```
3130

3231
### CMake Configuration Files
3332

3433
A CMake project is defined by a set of 'CMakeLists.txt' files located in the source tree
3534
(directories containing your source code). These describe your projects targets, source
3635
files etc.. For a simple single file project we only need a single 'CMakeLists.txt'
37-
alongside our `main.cxx` source file. Copy the contents from [Listing 1-2](#listing1-2).
36+
alongside our `main.cxx` source file. Copy the contents from below.
3837

39-
<span id="listing1-2" class="caption">Listing 1-2: Basic CMake configuration file.</span>
40-
41-
```haskell
42-
{{#include examples/hello_cmake/CMakeLists.txt}}
38+
```haskell,icon=%cmake,fp=CMakeLists.txt
39+
{{#include examples/hello_world/CMakeLists.txt}}
4340
```
4441

4542
Let's break down our `CMakeLists.txt` file. First we specify the minimum required version
4643
of CMake this project uses. This helps to ensure that any CMake features used in the
4744
projects configuration are available to end users and collaborators.
4845

49-
```haskell
50-
{{#include examples/hello_cmake/CMakeLists.txt:1}}
46+
```haskell,icon=%cmake,fp=CMakeLists.txt
47+
{{#include examples/hello_world/CMakeLists.txt:1}}
5148
```
5249

5350
We then define the basic information about our project such as its name, description,
5451
version and what languages it uses.
5552

56-
```haskell
57-
{{#include examples/hello_cmake/CMakeLists.txt:3:6}}
53+
```haskell,icon=%cmake,fp=CMakeLists.txt
54+
{{#include examples/hello_world/CMakeLists.txt:3:6}}
5855
```
5956

6057
In order to mark our `main.cxx` as an executable we use the `add_executable()` function
6158
where we specify the executable's name ie. the name of the target created from the
6259
executable as well as the source file used to make the executable.
6360

64-
```haskell
65-
{{#include examples/hello_cmake/CMakeLists.txt:8}}
61+
```haskell,icon=%cmake,fp=CMakeLists.txt
62+
{{#include examples/hello_world/CMakeLists.txt:8}}
6663
```
6764

6865
Finally, we can add compilation features; such as setting the C++ Standard to use for
6966
building the target, using the `target_compile_features()` function. Here we add the
70-
builtin CMake feature `cxx_std_20` to our executable which ensures it is built using the
71-
2020 C++ Standard.
67+
builtin CMake feature `cxx_std_17` to our executable which ensures it is built using the
68+
2017 C++ Standard.
7269

73-
```haskell
74-
{{#include examples/hello_cmake/CMakeLists.txt:9}}
70+
```haskell,icon=%cmake,fp=CMakeLists.txt
71+
{{#include examples/hello_world/CMakeLists.txt:9}}
7572
```
7673

7774
```admonish info
78-
See [Appendix D](../appendix/standard-versions.md) for more information on C++ Standards.
75+
See [Appendix C](../appendix/standard-versions.md) for more information on C++ Standards.
7976
```
8077

78+
<!--
8179
### CMake Presets
8280
8381
We can also specify presets for CMake that define different configurations by a unique
8482
name. These presets can be used to configure your project to compile on multiple
8583
different platforms as well as set various flags and options depending on how your want
8684
the project to be built. This is better than writing large 'CMakeLists.txt' files with
87-
complicated conditional logic that makes just *writing* the configuration complicated. A
88-
minimalistic `CMakePresets.json` file would look similar to [Listing 1-3](#listing1-3).
89-
90-
<span id="listing1-3" class="caption">Listing 1-3: Minimalistic CMake presets file.</span>
91-
92-
```json
93-
{{#include examples/hello_cmake/CMakePresets.json}}
94-
```
95-
96-
A `CMakePresets.json` file is starts with a key-value pair indicating the version of the
97-
preset engine to use from CMake. We also specify the minimum CMake version required for
98-
this project, similar to the first line [Listing 1-2](#listing1-2).
99-
100-
```json
101-
{{#include examples/hello_cmake/CMakePresets.json:2:7}}
102-
```
103-
104-
We then have a configuration array which stores our presets objects used for configuring
105-
our projects for different targets. All presets must have a unique name used to identify
106-
them.
107-
108-
```json
109-
{{#include examples/hello_cmake/CMakePresets.json:8}}
110-
// ... preset objects go here
111-
{{#include examples/hello_cmake/CMakePresets.json:13}}
112-
```
113-
114-
In our preset named "default" specify where we want the resulting binary to be put. In
115-
this case we specified it to be placed in the `build/` directory at the root of our
116-
project.
117-
118-
```json
119-
{{#include examples/hello_cmake/CMakePresets.json:9:12}}
120-
```
121-
122-
One final thing to mention is that `CMakePresets.json` files support macro expansions
123-
which allow you to obtain common variables. The syntax for expanding a macro is to use a
124-
dollar sign (`$`) followed by the variables identifier surrounded in braces (`{}`). We
125-
can see one being used in [Listing 1-3](#listing1-3) when we specify where our binary
126-
should be built. We can see that instead of hard coding a path or using relative path we
127-
can leverage CMake knowing where our projects root is (which is where the root
128-
`CMakeLists.txt` file is located) and obtain the root of our source directory using the
129-
`sourceDir` variable, hence its expansion being used on line 11 eg.
130-
`"binaryDir": "${sourceDir}/build"`. Variable names are always in camel case.
85+
complicated conditional logic that makes just *writing* the configuration complicated.
13186
13287
More information of CMake's presets can be found on CMake's official documentation
13388
[cmake-presets(7)](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html).
89+
-->
13490

13591
## Building and Running a CMake Project
13692

@@ -144,7 +100,7 @@ For our project we only have a single target which also happens to correspond to
144100
single preset so we can simply run the following to build our recipe.
145101

146102
```sh
147-
$ cmake --preset=default
103+
$ cmake -S . -B build
148104
-- The CXX compiler identification is GNU 11.4.0
149105
-- Detecting CXX compiler ABI info
150106
-- Detecting CXX compiler ABI info - done
@@ -153,33 +109,24 @@ $ cmake --preset=default
153109
-- Detecting CXX compile features - done
154110
-- Configuring done
155111
-- Generating done
156-
-- Build files have been written to: /home/user/projects/hello_cmake/build
112+
-- Build files have been written to: /home/user/projects/hello_world/build
157113
```
158114

159-
~~~admonish info
160-
If you do not want to use presets you can manually build the project with the following
161-
command.
162-
163-
```sh
164-
$ cmake -S . -B build
165-
```
166-
~~~
167-
168115
We can then build the target using the following command:
169116

170117
```sh
171118
$ cmake --build build
172-
[ 50%] Building CXX object CMakeFiles/hello_cmake.dir/main.cxx.o
173-
[100%] Linking CXX executable hello_cmake
174-
[100%] Built target hello_cmake
119+
[ 50%] Building CXX object CMakeFiles/hello_world.dir/main.cxx.o
120+
[100%] Linking CXX executable hello_world
121+
[100%] Built target hello_world
175122
```
176123

177-
This will produce a binary called `hello_cmake` in the `build/` directory on Linux and
178-
MacOS and the `build/Debug/` directory on Windows. We can run our program like normal.
124+
This will produce a binary called `hello_world` in the `build/` directory on Linux and
125+
macOS and the `build/Debug/` directory on Windows. We can run our program like normal.
179126

180127
```sh
181-
$ ./build/hello_cmake # ... or .\build\Debug\hello_cmake.exe on Windows
182-
Hello, CMake!
128+
$ ./build/hello_world # ... or .\build\Debug\hello_world.exe on Windows
129+
Hello, World!
183130
```
184131

185132
~~~admonish tip
@@ -190,11 +137,26 @@ CMake's `--config=<config>` flag during the build step. You can test creating a
190137
build by running the following command which should now produce and executable in the
191138
`build\Release\` directory.
192139
193-
```console
140+
```haskell,icon=,fp=CommandPrompt
194141
> cmake --build build --config=Release
195142
```
196143
~~~
197144

145+
## Adding Compiler Flags to CMake Build
146+
147+
Remember in the previous chapter how I stated that it is good to specify warning flags in
148+
your C++ builds to catch common bugs. We seem to have abandoned them when introducing
149+
CMake, do not fret, we will reinstate them now.
150+
151+
```haskell,icon=%cmake,CMakeLists.txt
152+
{{#include examples/hello_world/CMakeLists2.txt}}
153+
```
154+
155+
Yes, CMake has conditionals and yes they look a little weird but this is greatly the
156+
extent I will be discussing CMake until [chapter 06](../ch06/larger-projects.md) when
157+
we look multi-file project structures.
158+
159+
<!--
198160
## Compiling with Flags (Optional)
199161
200162
Often we want to have specific flags set for the compiler(s) we are using but because
@@ -273,4 +235,4 @@ $ cmake -S . -B build/windows-x86 --preset=windows-x86 # configure
273235
$ cmake --build build/windows-x86 --config=Release # build
274236
$ ./build/windows-x86/Release/<exe-name>.exe # execute
275237
```
276-
238+
-->

0 commit comments

Comments
 (0)