Skip to content

Commit 139420b

Browse files
committed
Move emscripten-specific intro to Project Setup
1 parent 81344a1 commit 139420b

2 files changed

Lines changed: 102 additions & 41 deletions

File tree

next/getting-started/hello-webgpu.md

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -252,25 +252,9 @@ wgpuInstanceRelease(instance);
252252

253253
### Building for the Web
254254

255-
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).
256256

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
270-
set_target_properties(App PROPERTIES SUFFIX ".html")
271-
```
272-
273-
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:
274258

275259
```{lit} C++, Create WebGPU instance (replace)
276260
// We create a descriptor

next/getting-started/project-setup.md

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ Project setup <span class="bullet">🟢</span>
77

88
*Resulting code:* [`step000`](https://github.com/eliemichel/LearnWebGPU-Code/tree/step000)
99

10-
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.
1113

1214
Requirements
1315
------------
1416

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.
1618

1719
```{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.
1921
```
2022

2123
### Linux
@@ -30,7 +32,7 @@ Other distributions have equivalent packages, make sure you have the commands `c
3032

3133
### Windows
3234

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.
3436

3537
### MacOS
3638

@@ -39,11 +41,12 @@ You can install CMake using `brew install cmake`, and [XCode](https://developer.
3941
Minimal project
4042
---------------
4143

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**.
4345

44-
Let us start with the classic hello world in `main.cpp`:
46+
Let us start with the classic **hello world** in `main.cpp`:
4547

4648
```{lit} C++, file: main.cpp
49+
// In file 'main.cpp'
4750
#include <iostream>
4851

4952
int main (int, char**) {
@@ -52,16 +55,17 @@ int main (int, char**) {
5255
}
5356
```
5457
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`:
5659
5760
```{lit} CMake, Define app target
61+
# In file 'CMakeLists.txt'
5862
add_executable(App main.cpp)
5963
```
6064

6165
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:
6266

6367
```{lit} CMake, file: CMakeLists.txt
64-
cmake_minimum_required(VERSION 3.0...3.25)
68+
cmake_minimum_required(VERSION 3.21...3.30)
6569
project(
6670
LearnWebGPU # name of the project, which will also be the name of the visual studio solution if you use it
6771
VERSION 0.1.0 # any version number
@@ -76,39 +80,67 @@ project(
7680
Building
7781
--------
7882

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:
8084

8185
```bash
8286
cd your/project/directory
8387
```
8488

8589
```{hint}
86-
From a Windows explorer 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**.
8791
```
8892

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):
9094

9195
```bash
9296
cmake . -B build
9397
```
9498

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:
96114

97115
```bash
98116
cmake --build build
99117
```
100118

101-
Then run the resulting program:
119+
Then **run** the resulting program:
102120

103121
```bash
104122
build/App # linux/macOS
105123
build\Debug\App.exe # Windows
106124
```
107125

126+
You should see the **expected output**:
127+
128+
```
129+
Hello, world!
130+
```
131+
108132
Recommended extras
109133
------------------
110134

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:
112144

113145
```{lit} CMake, Recommended extras
114146
set_target_properties(App PROPERTIES
@@ -119,11 +151,11 @@ set_target_properties(App PROPERTIES
119151
)
120152
```
121153

122-
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.
123155

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**.
125157

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**:
127159

128160
```{lit} CMake, Recommended extras (append)
129161
if (MSVC)
@@ -134,13 +166,12 @@ endif()
134166
```
135167

136168
```{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`.
138170
```
139171

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:
144175

145176
```{lit} CMake, Recommended extras (append)
146177
if (XCODE)
@@ -151,7 +182,13 @@ if (XCODE)
151182
endif()
152183
```
153184

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:
155192

156193
```{lit} CMake, Recommended extras (append)
157194
# NB: This only works if put in the top-level CMakeLists.txt
@@ -160,6 +197,46 @@ set_directory_properties(PROPERTIES
160197
)
161198
```
162199

200+
```{note}
201+
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
233+
set_target_properties(App PROPERTIES SUFFIX ".html")
234+
```
235+
236+
```{note}
237+
If you forget this, the cross-compilation will generate a `.wasm` and a `.js` file, but no `.html`.
238+
```
239+
163240
Conclusion
164241
----------
165242

0 commit comments

Comments
 (0)