You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The WebGPU distribution listed above are readily compatible with [Emscripten](https://emscripten.org/docs/getting_started/downloads.html) and if you have trouble with building your application for the web, you can consult [the dedicated appendix](../appendices/building-for-the-web.md).
255
+
The WebGPU distribution listed above are readily compatible with [Emscripten](https://emscripten.org/docs/getting_started/downloads.html).
256
256
257
-
As we will add a few options specific to the web build from time to time, we can add a section at the end of our `CMakeLists.txt`:
258
-
259
-
```{lit} CMake, file: CMakeLists.txt (append)
260
-
# Options that are specific to Emscripten
261
-
if (EMSCRIPTEN)
262
-
{{Emscripten-specific options}}
263
-
endif()
264
-
```
265
-
266
-
For now we only change the output extension so that it is an HTML web page (rather than a WebAssembly module or JavaScript library):
267
-
268
-
```{lit} CMake, Emscripten-specific options
269
-
# Generate a full web page rather than a simple WebAssembly module
For some reason the instance descriptor **must be null** (which means "use default") when using Emscripten, so we can already use our `WEBGPU_BACKEND_EMSCRIPTEN` macro:
257
+
For some reason though the instance descriptor **must be null** (which means "use default") when using Emscripten, so we can already use our `WEBGPU_BACKEND_EMSCRIPTEN` macro:
In our running example, we use [CMake](https://cmake.org/) to organize the compilation of the code. This is a very standard way of handling cross-platform builds, and we follow the idioms of [modern cmake](https://cliutils.gitlab.io/modern-cmake/).
10
+
In the recurring example we build throughout the chapters of this guide, we use [CMake](https://cmake.org/) to organize the compilation of the code. This is a **very standard** way of handling **cross-platform builds** in C++, and we follow the idioms of [Modern CMake](https://cliutils.gitlab.io/modern-cmake/).
11
+
12
+
In this first chapter, we set up a very basic C++ project, with **one source file** and **one `CMakeLists.txt` file** to tell how to build it in a cross-platform way.
11
13
12
14
Requirements
13
15
------------
14
16
15
-
All we need is CMake and a C++ compiler, instructions are detailed below per OS.
17
+
All we need to install is CMake and a C++ compiler, instructions are detailed below per OS.
16
18
17
19
```{hint}
18
-
After the installation, you can type `which cmake` (linux/macOS) or `where cmake` (Windows) to see whether your command line finds the full path to the `cmake` command. If not, make sure your `PATH` environment variable contains the directory where CMake is installed.
20
+
**After the installation**, you can type `which cmake` (linux/macOS) or `where cmake` (Windows) to see whether your command line finds the full path to the `cmake` command. If not, make sure your `PATH` environment variable contains the directory where CMake is installed.
19
21
```
20
22
21
23
### Linux
@@ -30,7 +32,7 @@ Other distributions have equivalent packages, make sure you have the commands `c
30
32
31
33
### Windows
32
34
33
-
Download and install CMake from [the download page](https://cmake.org/download/). You may use either [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [MinGW](https://www.mingw-w64.org/) as a compiler toolkit.
35
+
Download and install CMake from [the download page](https://cmake.org/download/). You may use either [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [MinGW](https://www.mingw-w64.org/) as the C++ compiler toolkit.
34
36
35
37
### MacOS
36
38
@@ -39,11 +41,12 @@ You can install CMake using `brew install cmake`, and [XCode](https://developer.
39
41
Minimal project
40
42
---------------
41
43
42
-
The most minimal project consists then in a `main.cpp` source file, and a `CMakeLists.txt` build file.
44
+
The most minimal project consists then in a `main.cpp`**source file**, and a `CMakeLists.txt`**build file**.
43
45
44
-
Let us start with the classic hello world in `main.cpp`:
46
+
Let us start with the classic **hello world** in `main.cpp`:
45
47
46
48
```{lit} C++, file: main.cpp
49
+
// In file 'main.cpp'
47
50
#include<iostream>
48
51
49
52
intmain (int, char**) {
@@ -52,16 +55,17 @@ int main (int, char**) {
52
55
}
53
56
```
54
57
55
-
In `CMakeLists.txt`, we specify that we want to create a *target* of type *executable*, called "App" (this will also be the name of the executable file), and whose source code is `main.cpp`:
58
+
In `CMakeLists.txt`, we specify that we want to create a **target** of type **executable**, called "App" (this will also be the name of the executable file), and whose source code is `main.cpp`:
56
59
57
60
```{lit} CMake, Define app target
61
+
# In file 'CMakeLists.txt'
58
62
add_executable(App main.cpp)
59
63
```
60
64
61
65
CMake also expects at the beginning of `CMakeLists.txt` to know the version of CMake the file is written for (minimum supported...your version) and some information about the project:
62
66
63
67
```{lit} CMake, file: CMakeLists.txt
64
-
cmake_minimum_required(VERSION 3.0...3.25)
68
+
cmake_minimum_required(VERSION 3.21...3.30)
65
69
project(
66
70
LearnWebGPU # name of the project, which will also be the name of the visual studio solution if you use it
67
71
VERSION 0.1.0 # any version number
@@ -76,39 +80,67 @@ project(
76
80
Building
77
81
--------
78
82
79
-
We are now ready to build our minimal project. Open a terminal and go to the directory where you have the `CMakeLists.txt` and `main.cpp` files:
83
+
We are now ready to **build our minimal project**. Open a **terminal** and go to the directory where you have the `CMakeLists.txt` and `main.cpp` files:
80
84
81
85
```bash
82
86
cd your/project/directory
83
87
```
84
88
85
89
```{hint}
86
-
From a Windowsexplorer window showing your project's directory, press Ctrl+L, then type `cmd` and hit return. This opens a terminal in the current directory.
90
+
From a **Windows** file explorer showing your project's directory, press Ctrl+L, then type `cmd` and hit return. This **opens a terminal in the current directory**.
87
91
```
88
92
89
-
Let us now ask CMake to create the build files for our project. We ask it to isolate the build files from our source code by placing them in a *build/* directory with the `-B build` option. This is very much recommended, in order to be able to easily distinguish these generated files from the ones we manually wrote (a.k.a. the source files):
93
+
Let us now ask CMake to create the build files for our project. We ask it to **isolate the build files** from our source code by placing them in a `build/` directory with the `-B build` option. This way, we can easily **distinguish** the generated build files from the ones we manually wrote (a.k.a. the source files):
90
94
91
95
```bash
92
96
cmake . -B build
93
97
```
94
98
95
-
This creates the build files for either `make`, Visual Studio or XCode depending on your system (you can use the `-G` options to force a particular build system, see `cmake -h` for more info). To finally build the program and generate the `App` (or `App.exe`) executable, you can either open the generated Visual Studio or XCode solution, or type in the terminal:
99
+
```{tip}
100
+
If you are using [`git`](https://git-scm.com/) to version your project (which I recommend), you may create a `.gitignore` file and add a line with `build/` in it to **prevent git from versioning** the generated build files.
101
+
```
102
+
103
+
After running the CMake command above, you should see a `build/` directory which contains either a `Makefile` for `make`, a `.sln` file for Visual Studio or an XCode project, depending on your system.
104
+
105
+
```{important}
106
+
Calling CMake just **_prepared_** the project for your compiler, but did not build anything. The idea is that our `CMakeLists.txt` file is the **source of truth** of compilation options, and CMake is able to adapt it to whichever platform you build for.
107
+
```
108
+
109
+
```{note}
110
+
You can use the `-G` options to **force a particular build system** (make, Visual Studio, XCode, ninja, etc.), see `cmake -h` for more info.
111
+
```
112
+
113
+
To finally **build** the program and generate the `App` (or `App.exe`) executable, you can either open the generated Visual Studio or XCode solution, or type in the terminal:
96
114
97
115
```bash
98
116
cmake --build build
99
117
```
100
118
101
-
Then run the resulting program:
119
+
Then **run** the resulting program:
102
120
103
121
```bash
104
122
build/App # linux/macOS
105
123
build\Debug\App.exe # Windows
106
124
```
107
125
126
+
You should see the **expected output**:
127
+
128
+
```
129
+
Hello, world!
130
+
```
131
+
108
132
Recommended extras
109
133
------------------
110
134
111
-
We set up some properties of the target `App` by calling somewhere after `add_executable` the `set_target_properties` command.
135
+
Good, we have a very minimal cross-platform C++ project running. Let us nonetheless **set up some key properties** of the target `App`.
136
+
137
+
```{important}
138
+
Some suggestions below are **specific** to a particular build tool (e.g., XCode, Visual Studio, emscripten, etc.). I recommend to **include all of them** even if you do not use that tool for now: it is harmless because we guard them with a proper `if ()` condition, and they **will come handy** the day you try to build for a different platform.
139
+
```
140
+
141
+
### C++ version
142
+
143
+
Somewhere **after** the `add_executable` statement in `CMakeLists.txt`, we call the `set_target_properties` command:
The `CXX_STANDARD` property is set to 17 to mean that we require C++17 (this will enable us to use some syntactic tricks later on, but is not mandatory per se). The `CXX_STANDARD_REQUIRED` property ensures that configuration fails if C++17 is not supported.
154
+
The `CXX_STANDARD` property is set to 17 to mean that we require **C++17** (this will enable us to use some syntactic tricks later on, but is not mandatory *per se*). The `CXX_STANDARD_REQUIRED` property ensures that configuration fails if C++17 is not supported.
123
155
124
-
The `CXX_EXTENSIONS` property is set to `OFF` to disable compiler specific extensions (for example, on GCC this will make CMake use `-std=c++17` rather than `-std=gnu++17` in the list of compilation flags).
156
+
The `CXX_EXTENSIONS` property is set to `OFF` to **disable compiler specific extensions** (for example, on GCC this will make CMake use `-std=c++17` rather than `-std=gnu++17` in the list of compilation flags). This will ease our **cross-platform development**.
125
157
126
-
The `COMPILE_WARNING_AS_ERROR` is turned on as a good practice, to make sure no warning is left ignored. Warnings are actually important, especially when learning a new language/library. To make sure we even have as many warnings as possible, we add some compile options:
158
+
The `COMPILE_WARNING_AS_ERROR` is turned on as a **good practice**, to make sure **no warning is left ignored**. Warnings are actually **important**, especially when learning a new language/library. To make sure we even have as many warnings as possible, we **add some compile options**:
127
159
128
160
```{lit} CMake, Recommended extras (append)
129
161
if (MSVC)
@@ -134,13 +166,12 @@ endif()
134
166
```
135
167
136
168
```{note}
137
-
In the accompanying code, I hid these details in the `target_treat_all_warnings_as_errors()` function defined in `utils.cmake` and included at the beginning of the `CMakeLists.txt`.
169
+
In the **accompanying code**, I hid these details in the `target_treat_all_warnings_as_errors()` function defined in `utils.cmake` and included at the beginning of the `CMakeLists.txt`.
138
170
```
139
171
140
-
On MacOS, CMake can generate XCode project files. However, by default, no *schemes* are
141
-
created, and XCode itself generates a scheme for each CMake target -- usually we only
142
-
want a scheme for our main target. Therefore, we set the `XCODE_GENERATE_SCHEME` property.
143
-
We will also already enable frame capture for GPU debugging.
172
+
### XCode
173
+
174
+
When **CMake detects that we build with XCode**, the `XCODE` variable is turned on. We use this to set XCode-specific properties on our `App` target:
144
175
145
176
```{lit} CMake, Recommended extras (append)
146
177
if (XCODE)
@@ -151,7 +182,13 @@ if (XCODE)
151
182
endif()
152
183
```
153
184
154
-
Lastly, we can ensure that when using Visual Studio the default target that builds and runs when pressing F5 is our `App` target:
185
+
The `XCODE_GENERATE_SCHEME` instructs CMake to generate what XCode calls a **schema** for our target. If we do not set this up, CMake does not provide any schema, and in consequence XCode will generate one for each CMake target (including all our dependencies).
186
+
187
+
The `XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE` property lets you run XCode's [Metal Debugger](https://developer.apple.com/documentation/xcode/metal-debugger) on our application. This may greatly help you on the long run, giving insights about what is happening on the GPU.
188
+
189
+
### Visual Studio
190
+
191
+
When using Visual Studio, we can **specify the default target** that builds and runs when pressing F5 (or hitting the "Run local debugger" button). This is done by setting the `VS_STARTUP_PROJECT` property of the project's root directory:
155
192
156
193
```{lit} CMake, Recommended extras (append)
157
194
# NB: This only works if put in the top-level CMakeLists.txt
No need to check that we are building with Visual Studio. **If we are not**, this directory property is just ignored.
202
+
```
203
+
204
+
### Building for the Web
205
+
206
+
One nice benefits of using WebGPU as our graphics API is that we can **build our application to run in a Web page**.
207
+
208
+
````{note}
209
+
To get started with [Emscripten](https://emscripten.org/docs/getting_started/downloads.html) and **cross-compile our app to WebAssembly**, you can consult [the dedicated appendix](../appendices/building-for-the-web.md).
210
+
211
+
What you mostly need to remember is to wrap the first call to CMake in `emcmake`:
212
+
213
+
```
214
+
# Create a build-web directory in which we configured the project to build
215
+
# with emscripten. You may use any regular cmake command line option here.
216
+
emcmake cmake -B build-web
217
+
```
218
+
````
219
+
220
+
We add a section dedicated to emscripten-specific options at the end of our `CMakeLists.txt`:
221
+
222
+
```{lit} CMake, file: CMakeLists.txt (append)
223
+
# Options that are specific to Emscripten
224
+
if (EMSCRIPTEN)
225
+
{{Emscripten-specific options}}
226
+
endif()
227
+
```
228
+
229
+
For now we only **change the output extension** so that it is an HTML web page (rather than a WebAssembly module or JavaScript library):
230
+
231
+
```{lit} CMake, Emscripten-specific options
232
+
# Generate a full web page rather than a simple WebAssembly module
0 commit comments