Skip to content

Commit 893442e

Browse files
authored
save
1 parent 99f81f0 commit 893442e

File tree

15 files changed

+114
-47
lines changed

15 files changed

+114
-47
lines changed

.devcontainer/devcontainer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"image": "mcr.microsoft.com/devcontainers/cpp",
3+
"updateContentCommand": "cargo install mdbook mdbook-cmdrun"
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "Hello world",
3+
"image": "mcr.microsoft.com/devcontainers/cpp",
4+
"workspaceFolder": "${localWorkspaceFolder}/src/hello-world"
5+
}

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,19 @@
88
![CMake](https://img.shields.io/static/v1?style=for-the-badge&message=CMake&color=064F8C&logo=CMake&logoColor=FFFFFF&label=)
99

1010
Make sure you've installed [mdBook](https://rust-lang.github.io/mdBook/guide/installation.html) and [CMake](https://cmake.org/download/). You'll also need to install [mdbook-cmdrun](https://github.com/FauconFan/mdbook-cmdrun). Run `mdbook serve` to see the live preview.
11+
12+
The custom `theme/highlight.js` is needed because the default mdBook `highlight.js` doesn't include the `cmake` language. The current custom build includes [all of the mdBook defaults](https://rust-lang.github.io/mdBook/format/theme/syntax-highlighting.html#supported-languages) plus `cmake`. Generate it using https://highlightjs.org/download and use the `./highlight.min.js` file from the resulting `.zip` download.
13+
14+
To create a new example:
15+
16+
1. Come up with a slug like `cool-feature`.
17+
2. Add it to `src/SUMMARY.md` like `- [Cool feature](cool-feature/index.md)`.
18+
3. Create a new folder to hold the example like `src/cool-feature`.
19+
4. Add a `README.md` to the new folder.
20+
5. Create your example. Take note of any dependencies it needs (Clang, clang-format, Vcpkg, Conan, etc.).
21+
6. Add a lot of comments to your code files to explain what's going on. The `README.md` is for shell commands. The code files are for other prose.
22+
7. `{{#include filename.txt}}` any relevant files in the `src/cool-feature/README.md` inside `` ``` `` code blocks.
23+
8. Add any shell commands to interact with the example to the `src/cool-feature/README.md`. Make sure to document them.
24+
9. (Optional) Use `<!-- cmdrun cmake ... -->` or similar inside a `` ``` `` code block to run that command and use its output at build time.
25+
10. Create a corresponding `.devcontainer/cool-feature/devcontainer.json` that will open the example's folder. Add any necessary dependencies to the dev container.
26+
11. Add an "Open in Codespaces" button to the `src/cool-feature/README.md`.

src/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# CMake by Example
2+
3+
CMake is an open source cross-platform meta build system that works on Windows, macOS, Linux, and more. It is designed to bridge the gap between the platform-specific build tools such as Ninja, GNU Make, BSD Make, Visual Studio, and Xcode. You can read more about CMake on the [official CMake.org website](https://cmake.org/). CMake is best known for its unmatched popularity as the primary C/C++ build tool.
4+
5+
*CMake by Example* is a hands-on introduction to how to use CMake to build C/C++ projects using annotated example projects. Make sure you have [installed the latest version of CMake on your system](https://cmake.org/download/). Check out the first [Hello world](hello-world.md) example to get started.
6+
7+
<!-- This works because our `SUMMARY.md` just so happens to match the format that we need here. -->
8+
{{#include SUMMARY.md:7:}}

src/SUMMARY.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Summary
22

3-
[CMake by Example](index.md)
3+
[CMake by Example](README.md)
44

55
---
66

7-
- [Hello world](hello-world.md)
8-
- [Values](values.md)
7+
- [Hello world](hello-world/README.md)
8+
- [Logging](logging/README.md)
9+
- [Values](values/README.md)
910
- [Variables]()
1011
- [Executables]()
1112
- [Libraries]()
@@ -29,7 +30,6 @@
2930
- [HTTP requests]()
3031
- [String functions]()
3132
- [JSON]()
32-
- [Logging]()
3333
- [Environment variables]()
3434
- [Feature detection]()
3535
- [clang-format]()

src/hello-world.md

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

src/hello-world/.devcontainer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "Hello world 2",
3+
"image": "mcr.microsoft.com/devcontainers/cpp",
4+
"workspaceFolder": "${localWorkspaceFolder}/src/hello-world"
5+
}

src/hello-world/CMakeLists.txt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
1+
# First we require a minimum version of CMake. It's a good idea to choose
2+
# something recent. You can find the latest version on the CMake website
3+
# https://cmake.org/download/. This function is HIGHLY RECOMMENDED. It should be
4+
# before even the project() function.
15
cmake_minimum_required(VERSION 3.30)
26

7+
# Next we define a project. Think of a project as similar to a Python package, a
8+
# JavaScript package, a Rust package, etc. This project() function call will
9+
# define all subsequent targets (executables, libraries, etc.) in the scope of
10+
# this project. You may specify more than just a project name:
11+
#
12+
# project(<PROJECT-NAME>
13+
# [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
14+
# [DESCRIPTION <project-description-string>]
15+
# [HOMEPAGE_URL <url-string>]
16+
# [LANGUAGES <language-name>...])
317
project(hello-world)
418

5-
add_executable(hello-world main.c)
19+
# Finally, we add an executable target. This will create an executable named
20+
# hello-world from the source file main.c. You are able to specify more than one
21+
# source file if you wish:
22+
#
23+
# add_executable(<name> <options>... <sources>...)
24+
#
25+
# For example: add_executable(hello-world main.c other.c). For now we only need
26+
# one main.c file.
27+
add_executable(hello-world main.c)

src/hello-world/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Hello world
2+
3+
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/jcbhmr/cmakebyexample.jcbhmr.com?quickstart=1&devcontainer_path=src%2Fhello-world%2F.devcontainer.json)
4+
5+
```c
6+
{{#include main.c}}
7+
```
8+
9+
```cmake
10+
{{#include CMakeLists.txt}}
11+
```
12+
13+
CMake isn't actually a build system itself. It's a meta build system. CMake takes your imperative build instructions from the CMakeLists.txt script and generates the complicated structure that each platform-specific build tool requires. For example, GNU Makefiles on Linux, Xcode projects on macOS, and Visual Studio solutions on Windows. This is called "configuring". You can perform the configure step by running `cmake`. **But** by default that creates a lot of files in the current working directory. That gets messy with complicated `.gitignore` patterns and such. It's much easier to perform an *out of source build* where we tell CMake to put those files in another folder like `./build/` instead of `./`. That's where the `-B build` flag comes in.
14+
15+
```sh
16+
cmake -B ./build/
17+
```
18+
19+
```
20+
<!-- cmdrun cmake -B ./build/ -->
21+
```
22+
23+
Now that we've generated the platform-specific build system files in `./build/`, we can tell CMake to invoke `make`, `msbuild`, `ninja`, or another build command in that directory to finally build our project. This stage is aptly called "building". You can perform the build step by running `cmake --build <configure_output_folder>` where `<configure_output_folder>` is the folder you specified with the `-B` flag. In our case, that's `./build/`.
24+
25+
```sh
26+
cmake --build ./build/
27+
```
28+
29+
```
30+
<!-- cmdrun cmake --build ./build/ -->
31+
```
32+
33+
And finally we can run the executable that was built in `./build/`. The executable is named `hello-world` because that's the target name we specified in the `add_executable()` function in `CMakeLists.txt`.
34+
35+
```sh
36+
./build/hello-world
37+
```
38+
39+
```
40+
<!-- cmdrun ./build/hello-world -->
41+
```

src/hello-world/main.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
// You can compile and run this program directly without CMake using a C
2+
// compiler manually. Here's how you might do so with GCC:
3+
//
4+
// gcc -o hello-world main.c
5+
// ./hello-world
6+
17
#include <stdio.h>
28

39
int main() {
410
puts("Hello, World!");
511
return 0;
612
}
7-
8-
// You can compile and run this program directly without CMake using a C
9-
// compiler manually. Here's how you might do so with GCC:
10-
//
11-
// gcc -o hello-world main.c
12-
// ./hello-world

0 commit comments

Comments
 (0)