summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clangd3
-rw-r--r--.zed/debug.json56
-rw-r--r--.zed/tasks.json68
-rw-r--r--IDE_INTEGRATION.md198
-rw-r--r--README.md1
-rw-r--r--meson.build2
6 files changed, 327 insertions, 1 deletions
diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..af6672d
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,3 @@
+# Meson's Ninja backend generates this database during setup.
+CompileFlags:
+ CompilationDatabase: build
diff --git a/.zed/debug.json b/.zed/debug.json
new file mode 100644
index 0000000..8e54bf5
--- /dev/null
+++ b/.zed/debug.json
@@ -0,0 +1,56 @@
+[
+ {
+ "label": "YASL: debug hello",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/yasl-hello",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: debug simple window",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/yasl-example",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: debug tablet",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/yasl-tablet",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: debug notepad",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/yasl-notepad",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: debug game",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/yasl-game",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: debug lifecycle test (no display required)",
+ "adapter": "CodeLLDB",
+ "request": "launch",
+ "build": "YASL: build for debugger",
+ "stopOnEntry": true,
+ "program": "$ZED_WORKTREE_ROOT/build/tests/yasl-test",
+ "cwd": "$ZED_WORKTREE_ROOT"
+ }
+]
diff --git a/.zed/tasks.json b/.zed/tasks.json
new file mode 100644
index 0000000..6df4810
--- /dev/null
+++ b/.zed/tasks.json
@@ -0,0 +1,68 @@
+[
+ {
+ "label": "YASL: configure debug build",
+ "command": "meson",
+ "args": ["setup", "build", "--backend=ninja", "--buildtype=debug"],
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: reconfigure",
+ "command": "meson",
+ "args": ["setup", "--reconfigure", "build"],
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: build",
+ "command": "meson",
+ "args": ["compile", "-C", "build"],
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: build for debugger",
+ "command": "meson setup --reconfigure build --backend=ninja -Dbuildtype=debug -Ddebug=true -Doptimization=0 -Db_lto=false && meson compile -C build",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ },
+ {
+ "label": "YASL: test",
+ "command": "meson",
+ "args": ["test", "-C", "build", "--print-errorlogs"],
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: benchmark",
+ "command": "meson",
+ "args": ["test", "-C", "build", "--benchmark", "--verbose"],
+ "cwd": "$ZED_WORKTREE_ROOT"
+ },
+ {
+ "label": "YASL: run hello",
+ "command": "meson compile -C build yasl-hello && exec ./build/yasl-hello",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ },
+ {
+ "label": "YASL: run simple window",
+ "command": "meson compile -C build yasl-example && exec ./build/yasl-example",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ },
+ {
+ "label": "YASL: run tablet",
+ "command": "meson compile -C build yasl-tablet && exec ./build/yasl-tablet",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ },
+ {
+ "label": "YASL: run notepad",
+ "command": "meson compile -C build yasl-notepad && exec ./build/yasl-notepad",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ },
+ {
+ "label": "YASL: run game",
+ "command": "meson compile -C build yasl-game && exec ./build/yasl-game",
+ "cwd": "$ZED_WORKTREE_ROOT",
+ "shell": { "program": "sh" }
+ }
+]
diff --git a/IDE_INTEGRATION.md b/IDE_INTEGRATION.md
new file mode 100644
index 0000000..67ba96e
--- /dev/null
+++ b/IDE_INTEGRATION.md
@@ -0,0 +1,198 @@
+# IDE integration
+
+YASL includes Zed debugger profiles for stepping from example applications into
+the library's display and window creation code. Open the repository root (the
+directory containing `meson.build`) as your Zed project. The shared configuration
+uses `build/` for the build directory on Linux and macOS.
+
+## Prerequisites
+
+Install Zed, a C23 compiler, Meson 1.6 or newer, Ninja, pkg-config, and Python 3.
+A C++ compiler enables the optional public-header compatibility test. Install
+the backend development dependencies described in
+[Getting started](docs/getting-started.md#build-and-run): at least one of Wayland
+or X11 on Linux, or the macOS 14+ SDK on macOS. Running windows on macOS also
+requires a Metal-capable device.
+
+[Zed's C support](https://zed.dev/docs/languages/c) includes clangd for code
+completion, diagnostics, and navigation, and CodeLLDB for debugging. Allow Zed
+to obtain these tools when prompted, or configure your existing installations
+in your personal Zed settings. Use a recent clangd with C23 support.
+
+Make sure `meson`, `ninja`, your compiler, `pkg-config`, and `python3` are on the
+PATH visible to Zed's terminal. You can open the project from an initialized
+terminal with `zed .` when Zed's CLI is installed. On macOS, if your toolchain
+defaults to an older deployment target, launch from a terminal with
+`MACOSX_DEPLOYMENT_TARGET=14.0` (or newer) exported before configuring.
+
+## Start debugging window creation
+
+1. Save your changes and open `examples/hello.c`.
+2. Set gutter breakpoints on the calls to `yasl_display_open()` and
+ `yasl_surface_create_toplevel()` in `main()`.
+3. Open the command palette (`Ctrl+Shift+P` on Linux, `Cmd+Shift+P` on macOS),
+ run `debugger: start`, and choose **YASL: debug hello**.
+4. The debugger prepares the build and pauses on entry. Continue to the display
+ creation breakpoint, then use **Step Into** to enter YASL's implementation in
+ `src/common/backend.c`. Continue to the surface creation breakpoint and step
+ into `yasl_surface_create_toplevel()` and `yasl_create_toplevel()`.
+5. Step into `d->ops->surface_create_toplevel(...)` to reach native window
+ creation. Inspect `spec`, `d`, local variables, and the call stack in Zed's
+ debug panel. Use **Step Over** for calls you want to execute without entering.
+
+Every debug profile runs **YASL: build for debugger** before launching. This
+task creates or reconfigures `build/` with debug symbols, optimization disabled,
+and LTO disabled, then builds the library and examples. It explicitly sets
+`buildtype=debug`, `debug=true`, `optimization=0`, and `b_lto=false`, including
+when `build/` was previously a release or customized build. Other Meson options,
+including backend selection, are preserved. Both the example and YASL have
+source-level debug information; the shared-library examples load the library
+from the Meson build tree.
+
+Profiles pause on entry through CodeLLDB's `stopOnEntry` setting, so initialization
+does not run before you can inspect the session. To launch directly to your
+breakpoints instead, set `"stopOnEntry": false` in the desired profile. See
+[CodeLLDB's launch settings](https://github.com/vadimcn/codelldb/blob/master/MANUAL.md#launching-a-new-process).
+
+Native creation follows the backend selected at runtime:
+
+| Backend | Window creation implementation |
+| --- | --- |
+| Wayland | `wayland_surface_create_toplevel()` in `src/platform/wayland/surface.c` |
+| X11 | `create_toplevel()` in `src/platform/x11/window.c` |
+| Cocoa | `cocoa_surface_create_toplevel()` in `src/platform/cocoa/window.m` |
+
+You can also put a source breakpoint directly in these functions before
+launching. A breakpoint in a backend that is disabled or not selected will not
+be hit. In the notepad and game examples, `yasl_run()` opens the display before
+calling the example's initialization callback; set a breakpoint in `yasl_run()`
+in `src/common/app.c` to follow that path.
+
+## Configure and build without launching
+
+1. Open the command palette (`Ctrl+Shift+P` on Linux, `Cmd+Shift+P` on macOS).
+2. Run `task: spawn`, then select **YASL: configure debug build**.
+3. Run **YASL: build** from the same task picker.
+4. Open `examples/hello.c` or a file in `src/` to use completion and navigation.
+
+The configure task runs:
+
+```sh
+meson setup build --backend=ninja --buildtype=debug
+```
+
+Meson's Ninja backend writes `build/compile_commands.json`. The root
+[.clangd](.clangd) points clangd at that directory, so it uses Meson's actual
+include paths, C standard, and enabled-backend definitions. Keep the generated
+database in the ignored build directory; no root-level copy or symlink is
+needed. The same configuration works with other clangd-based editors. See
+[clangd's compilation database setting](https://clangd.llvm.org/config#compilationdatabase).
+
+If `build/` is already configured, the configure task leaves its existing
+options in place. To change an existing build to debug, run this in Zed's
+terminal:
+
+```sh
+meson configure build -Dbuildtype=debug
+```
+
+Save edited files before building, running, or debugging. Use **YASL:
+reconfigure** to rerun Meson configuration and refresh its metadata. Meson also
+regenerates the build automatically when build definitions change.
+
+## Tasks and examples
+
+The project tasks live in [.zed/tasks.json](.zed/tasks.json). Select them with
+`task: spawn`; `task: rerun` repeats the last task. See
+[Zed's task documentation](https://zed.dev/docs/tasks) for personal keybindings.
+
+| Task | Behavior |
+| --- | --- |
+| YASL: configure debug build | Set up `build/` with Ninja and debug symbols. |
+| YASL: reconfigure | Reconfigure an existing `build/`, preserving its options. |
+| YASL: build | Compile the library, examples, and enabled tests. |
+| YASL: build for debugger | Configure symbols and disable optimization/LTO, then build. |
+| YASL: test | Build as needed and run enabled tests, printing failure logs. |
+| YASL: benchmark | Build as needed and run Meson's registered benchmarks. |
+| YASL: run hello | Build and launch `yasl-hello`. |
+| YASL: run simple window | Build and launch `yasl-example`. |
+| YASL: run tablet | Build and launch `yasl-tablet`. |
+| YASL: run notepad | Build and launch `yasl-notepad`. |
+| YASL: run game | Build and launch `yasl-game`. |
+
+Each run task builds its executable before launching and stops if compilation
+fails. Run tasks explicitly use `sh` for their compound command. All tasks use
+the repository root as their working directory, including when a nested source
+file is active.
+
+Examples need a desktop connection. On Linux, run Zed in your desktop session
+so the launched program inherits `WAYLAND_DISPLAY`/`DISPLAY` and
+`XDG_RUNTIME_DIR` as appropriate. Most tests can run without a display, but the
+currently registered `app-runner` test opens a window even in a default build.
+`app-input-destroy` also needs a Wayland compositor when `WAYLAND_DISPLAY` is
+set. Run the full suite in a desktop session with the corresponding backend
+enabled; additional tests retain their configured requirements.
+
+## Debugging
+
+The profiles in [.zed/debug.json](.zed/debug.json) use CodeLLDB. Run
+`debugger: start` from the command palette and select an example. Profiles cover
+hello, simple window, tablet, notepad, game, and the lifecycle test
+(`build/tests/yasl-test`), which needs no display. Each profile builds through
+**YASL: build for debugger** and pauses on entry.
+See [Zed's debugger documentation](https://zed.dev/docs/debugger).
+
+To debug another test, copy the lifecycle profile and change its `label` and
+`program` to the executable under `build/tests/`. To pass example arguments,
+add an `args` array to a debug profile; for example, the tablet profile accepts
+`"args": ["--backend", "x11"]` when that backend is enabled.
+
+## Backend options and additional builds
+
+Linux backend selection defaults to automatic dependency detection. To require
+X11 and disable Wayland in the IDE build, run:
+
+```sh
+meson configure build -Dx11=enabled -Dwayland=disabled
+meson compile -C build
+```
+
+Restore automatic selection with `-Dx11=auto -Dwayland=auto`. Integration tests
+are opt-in through `-Dintegration_tests=true`; their server dependencies and
+desktop requirements are documented in [Testing](docs/testing.md).
+
+For sanitizers or a different compiler, prefer a separate build directory:
+
+```sh
+meson setup build-sanitize -Db_sanitize=address,undefined
+meson test -C build-sanitize --print-errorlogs
+```
+
+The checked-in Zed tasks and profiles continue to target `build/`. To use a
+different directory throughout the IDE, update the tasks' build arguments and
+run commands, debugger program paths, and `.clangd`'s `CompilationDatabase`
+together. Ignore additional build directories locally (for example through
+`.git/info/exclude`) and keep machine-specific tool paths out of shared files.
+
+## Troubleshooting
+
+- **Missing headers or incorrect backend diagnostics:** confirm that
+ `build/compile_commands.json` exists, build successfully, then run
+ `editor: restart language server`. clangd analyzes the backend configuration
+ in that database; disabled native backends may lack their SDK headers.
+- **C23 syntax errors in the editor:** update clangd; the compiler used by Meson
+ and the clangd used by Zed are separate tools.
+- **A task cannot find Meson or a compiler:** check `command -v meson ninja cc`
+ in Zed's terminal and fix the PATH used by Zed and its task shell.
+- **No window opens:** check the desktop environment and enabled backends.
+ Use the lifecycle debug profile to check debugging without a display.
+- **`app-runner` or `app-input-destroy` fails at startup:** check that the test
+ can connect to the inherited desktop session. For a headless check of the
+ lifecycle test alone, run `meson test -C build basic --print-errorlogs`.
+- **Breakpoints do not bind:** use a **YASL: debug ...** profile so the debugger
+ build task runs, and confirm the executable and library come from `build/`.
+ Shared-library breakpoints may remain pending until the library loads. Check
+ that a native backend breakpoint belongs to the enabled, selected backend.
+- **Configuration fails on macOS:** check the SDK and deployment target against
+ [Getting started](docs/getting-started.md#build-and-run). Compiler or SDK
+ changes may require a fresh build directory.
diff --git a/README.md b/README.md
index 35b12ed..5f0d4a6 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ for platform capabilities and limits.
- [API policy](docs/api-policy.md), [migration notes](docs/migrating.md), and
[contributing](CONTRIBUTING.md).
- [Tests, tablet example, and benchmarks](docs/testing.md).
+- [IDE integration](IDE_INTEGRATION.md): step through example and window creation code with Zed's debugger.
## Build a window
diff --git a/meson.build b/meson.build
index 201de74..b0ea8e8 100644
--- a/meson.build
+++ b/meson.build
@@ -160,7 +160,7 @@ game_example = executable(
subdir('tests')
doc_dir = get_option('datadir') / 'doc' / 'yasl'
-install_data('README.md', 'CONTRIBUTING.md', 'Doxyfile', 'LICENSE', install_dir: doc_dir)
+install_data('README.md', 'CONTRIBUTING.md', 'IDE_INTEGRATION.md', 'Doxyfile', 'LICENSE', install_dir: doc_dir)
# Preserve source-relative links and keep the reference buildable offline.
install_subdir('docs', install_dir: doc_dir)
install_subdir('examples', install_dir: doc_dir)