mirror of
https://github.com/Mudlet/Mudlet
synced 2026-08-13 18:26:27 -04:00
Infra: Add CMake presets for every platform, and one home for AI assistant skills (#9742)
#### Brief overview of PR changes/additions - Adds `CMakePresets.json` with configure, build and test presets for macOS, Linux and Windows, including sanitizer and static-analysis variants. Each is gated on the host system, so a listing only offers what the current machine can build. - Consolidates the AI assistant skills into `.agents/skills/`, which Claude Code, GitHub Copilot and Cursor all read, replacing two copies that had drifted into contradicting each other. - Corrects the build documentation: the Windows toolchain is CLANG64 rather than MinGW64, and the previous "no need to specify number of jobs" advice holds only for Ninja. #### Motivation for adding to Mudlet The instructions presented platform-specific build advice as though it were universal, so following them on the wrong platform produced either an unbounded parallel build or a toolchain the setup scripts refuse to run. #### Other info (issues closed, discussion etc) `windows-debug` has been exercised on Windows: `CI/setup-windows-sdk.sh` in an MSYS2 CLANG64 shell, then configure and build both to completion against Qt 6.11.1 and Clang 22.1.7. `cmake --list-presets` correctly offered only `windows-debug` there. Note that `windows-debug` is a Debug configuration, whereas `CI/build-mudlet-for-windows.sh` builds Release, so the two are not equivalent. `.claude/skills` is a symlink to `.agents/skills`, following the existing pattern used by `CLAUDE.md`, `AGENTS.md` and `.cursorrules`. On Windows checkouts without `core.symlinks` it lands as a plain file, in which case Copilot and Cursor still read `.agents/skills` directly. **Test case:** `cmake --preset macos-debug && cmake --build --preset macos-debug`, then `ctest --preset macos-debug`. `cmake --list-presets` should offer only the current platform's presets, and a variant such as `macos-debug-nosan` should build into `build-macos-debug-nosan/` while leaving `build/` untouched. --------- Signed-off-by: Michael Conley <sousesider@gmail.com>
This commit is contained in:
parent
6c2d2444b2
commit
6705cadd11
8 changed files with 579 additions and 111 deletions
124
.agents/skills/build-mudlet/SKILL.md
Normal file
124
.agents/skills/build-mudlet/SKILL.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
name: build-mudlet
|
||||
description: >-
|
||||
Read before running any cmake, ninja or make command in this repository, and when asked to
|
||||
build, rebuild, compile, or run Mudlet locally. Gives the correct per-platform configure and
|
||||
build invocation, and the parallelism pitfalls that make builds slow or thrash the machine.
|
||||
license: GPL-2.0-or-later
|
||||
---
|
||||
|
||||
## When to use
|
||||
|
||||
Read this **before** typing a build command, not after one fails. The correct invocation differs
|
||||
per platform, and the wrong one is not merely slower — see Pitfalls.
|
||||
|
||||
## Use a preset — every platform, one command
|
||||
|
||||
`CMakePresets.json` in the repository root encodes the generator, build type and sanitizer
|
||||
settings, so no platform-specific flags need to be remembered or typed. Run
|
||||
`cmake --list-presets` to see the ones available on the current machine.
|
||||
|
||||
Presets need CMake 3.25.1 or newer, which is the same floor `CMakeLists.txt` already sets for
|
||||
building Mudlet at all. An older CMake reports an unknown argument or an unsupported preset
|
||||
version rather than anything informative, so check `cmake --version` if `--preset` is rejected.
|
||||
|
||||
```bash
|
||||
cmake --preset macos-debug # configure
|
||||
cmake --build --preset macos-debug # build
|
||||
ctest --preset macos-debug # run the test suite
|
||||
```
|
||||
|
||||
| Preset | Platform | Notes |
|
||||
| --- | --- | --- |
|
||||
| `macos-debug` / `linux-debug` | macOS / Linux | Ninja, Debug, AddressSanitizer on |
|
||||
| `windows-debug` | Windows | MSYS2 CLANG64, Ninja, Debug |
|
||||
| `<platform>-debug-nosan` | macOS / Linux | No sanitizers — faster to build and to run |
|
||||
| `<platform>-debug-tsan` | macOS / Linux | ThreadSanitizer instead of AddressSanitizer |
|
||||
| `<platform>-debug-ubsan` | macOS / Linux | UndefinedBehaviorSanitizer |
|
||||
| `<platform>-static-analysis` | macOS / Linux | Runs clang-tidy and cppcheck during compilation |
|
||||
| `linux-lowspec` | Linux | No sanitizers, no updater, no 3D mapper, 2 jobs — Raspberry Pi and similar |
|
||||
|
||||
Every configure preset has a matching build and test preset of the same name, and all three are
|
||||
conditioned on the host system — so `cmake --list-presets` on macOS will not offer `linux-debug`,
|
||||
and `ctest --preset X` always runs against the tree that `cmake --build --preset X` produced.
|
||||
|
||||
The plain `<platform>-debug` presets build into `build/`. Every variant builds into
|
||||
`build-<preset-name>/` instead, so an AddressSanitizer tree and a sanitizer-free tree can coexist
|
||||
without forcing each other to rebuild. The `/build*` entry in `.gitignore` covers all of them.
|
||||
|
||||
### Qt discovery
|
||||
|
||||
The presets do not pin a Qt location. CMake installed via Homebrew or a distribution package
|
||||
finds Qt on its default search path. If configuring fails to find Qt — likely with a CMake from
|
||||
the Qt online installer — pass the prefix explicitly:
|
||||
|
||||
```bash
|
||||
cmake --preset macos-debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt6)"
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
Builds run under MSYS2. Use the **CLANG64** environment: `CI/setup-windows-sdk.sh`, which installs
|
||||
the dependencies, accepts only that one and exits on any other `MSYSTEM`. Open a CLANG64 shell, not
|
||||
MINGW64, and make sure it is a real MSYS2 shell — Git for Windows' bash can carry an inherited
|
||||
`MSYSTEM` that makes it look like one, in which case `MSYSTEM_PREFIX` is empty.
|
||||
|
||||
The preset itself is not tied to a particular environment: it reads `MSYSTEM_PREFIX`, which MSYS2
|
||||
sets in each of its shells, so it follows whichever one is provisioned. On an ARM64 host the native
|
||||
environment is `CLANGARM64`, which the setup script does not currently handle, so dependencies have
|
||||
to come from a CLANG64 shell.
|
||||
|
||||
Sanitizers are not enabled on Windows, so there is no `-nosan` variant.
|
||||
|
||||
## Running the result
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
./build/src/mudlet.app/Contents/MacOS/mudlet
|
||||
|
||||
# Linux
|
||||
./build/src/mudlet
|
||||
```
|
||||
|
||||
Mudlet is a graphical desktop application; launching it opens a window. Variant presets put the
|
||||
binary under `build-<preset-name>/` instead. Allow up to 10 minutes for a full build.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
**Never pass `--parallel` without a job count on a Makefiles build.** `cmake --build . --parallel`
|
||||
with no number passes a bare `-j` to make, which imposes no limit on concurrent jobs: make starts
|
||||
as many compilers as the dependency graph allows, exhausting RAM and swap. Ninja defaults to a
|
||||
bounded job count, which is why the presets use it. In a pre-existing Makefiles tree, use
|
||||
`make -j $(nproc)` on Linux or `make -j $(sysctl -n hw.ncpu)` on macOS.
|
||||
|
||||
**ccache is wired in automatically** — `CMakeLists.txt` sets it as the compiler launcher whenever
|
||||
ccache is installed. A full cache evicts objects continuously, so switching branches can trigger a
|
||||
near-full rebuild. Run `ccache -s`; if `Cache size` has reached `Max cache size`, raise it with
|
||||
`ccache -M <n>G`.
|
||||
|
||||
**Sanitizers are on by default** on every non-Windows build, regardless of build type
|
||||
(`src/cmake/EnableSanitizers.cmake` defaults `USE_SANITIZER` to `address`). They cost both compile
|
||||
time and runtime speed. Use a `-nosan` preset when not chasing a memory bug.
|
||||
|
||||
For a combination the presets do not cover, pass a **CMake list — semicolon-separated, not
|
||||
comma-separated**: `-DUSE_SANITIZER="Address;Undefined"`. A comma-separated value is treated as one
|
||||
name, which silently skips the per-sanitizer options such as `-fno-omit-frame-pointer`.
|
||||
|
||||
Usable names are `Address`, `Thread` and `Undefined` on macOS, plus `Memory` and `Leak` on Linux.
|
||||
`MemoryWithOrigins` appears in the `USE_SANITIZER` cache docstring but has no mapping declared, so
|
||||
it always fails. An unavailable or incompatible selection raises a `SEND_ERROR`: configure runs to
|
||||
completion, but generation is blocked.
|
||||
|
||||
**Static analysis** (`<platform>-static-analysis`) needs clang-tidy and cppcheck on `PATH`. They
|
||||
are independent: whichever is present runs. A missing clang-tidy produces a CMake warning, but a
|
||||
missing cppcheck only prints a `STATUS` line that is easy to miss — so check the configure output
|
||||
rather than assuming both ran. On macOS, Homebrew's llvm is keg-only, so clang-tidy is not on
|
||||
`PATH` by default.
|
||||
|
||||
**Configuring a second generator in an existing build directory fails.** CMake cannot switch
|
||||
generator in place; configure into a fresh directory instead.
|
||||
|
||||
## Related
|
||||
|
||||
- `docs/platform-builds.md` — platform detail and the compile-time debugging defines
|
||||
- <https://wiki.mudlet.org/w/Compiling_Mudlet> — full setup, including dependency installation
|
||||
130
.agents/skills/open-pr/SKILL.md
Normal file
130
.agents/skills/open-pr/SKILL.md
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
---
|
||||
name: open-pr
|
||||
description: >-
|
||||
Publish the current branch and open a pull request against the upstream Mudlet repository,
|
||||
using the project's PR template and the title prefix that Danger enforces. Use when asked to
|
||||
open a PR, create a pull request, or push changes upstream.
|
||||
license: GPL-2.0-or-later
|
||||
argument-hint: Optional hint about what this PR does (e.g. "adds shimmer blink effect")
|
||||
user-invocable: true
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
## When to use
|
||||
|
||||
Use when the user asks to open a pull request, create a PR, or push their changes upstream. This
|
||||
publishes the current branch to their fork if needed, then opens a PR against upstream
|
||||
`development`.
|
||||
|
||||
## Procedure
|
||||
|
||||
1. **Gather context.** Run `git status --porcelain` first. If anything is uncommitted, stop: ask
|
||||
the user to commit what belongs in the PR, or to confirm explicitly that it should be left out.
|
||||
A pull request is built from commits, so uncommitted work is silently absent from it.
|
||||
|
||||
Then run `git log upstream/development..HEAD --oneline` for the commit messages,
|
||||
`git diff upstream/development...HEAD` to see what actually changed, and
|
||||
`git branch --show-current` for the branch name. An empty commit list means there is nothing to
|
||||
open a pull request for.
|
||||
|
||||
`git branch --show-current` prints nothing on a detached HEAD. If it is empty, stop and ask the
|
||||
user to check out a named branch — every later step needs that name, and an empty one produces
|
||||
a malformed push and an unusable `--head`.
|
||||
|
||||
2. **Choose the title prefix.** `docs/CONTRIBUTING.md` states the rule and Danger enforces it on
|
||||
every PR. Choosing between the four is the part that is not written down elsewhere:
|
||||
|
||||
| Prefix | Use for |
|
||||
| --- | --- |
|
||||
| `Fix: ` | bug fixes visible to users |
|
||||
| `Improve: ` | enhancements to existing user-facing functionality |
|
||||
| `Add: ` | new user-facing features or capabilities |
|
||||
| `Infra: ` | build system, CI, tooling, refactoring, and other non-player-visible changes |
|
||||
|
||||
Distinguishing the last two: user-visible behavior change is `Improve`, everything internal is
|
||||
`Infra`, however large the diff.
|
||||
|
||||
3. **Write the title.** Use the exact form `Prefix: Summary` — capitalized prefix, colon, single
|
||||
space, then a summary whose first word is also capitalized. Keep the summary short and
|
||||
understandable to a non-technical reader; it becomes a line in the PTB changelog, which is why
|
||||
the casing is worth being consistent about even though Danger's check is case-insensitive and
|
||||
does not require the colon. Danger warns on overly long titles, so keep it brief.
|
||||
|
||||
Write in American English, matching the rest of the project's user-facing text — "color" not
|
||||
"colour", "standardize" not "standardise".
|
||||
|
||||
```
|
||||
Fix: Profiles named "." or ".." no longer delete every profile when removed
|
||||
Improve: OSC 8 hyperlink handling, and a setting to turn it off
|
||||
Add: Text-to-speech support for incoming game text
|
||||
Infra: Tidy up how CI installs Lua
|
||||
```
|
||||
|
||||
Dependabot raises its own PRs as `Infrastructure: Bump ...`; that is generated upstream and is
|
||||
not something to correct by hand.
|
||||
|
||||
4. **Draft the body.** Read `.github/PULL_REQUEST_TEMPLATE.md` and fill in its headings — read it
|
||||
rather than reproducing it here, so this skill cannot drift from the real template. Note that
|
||||
passing `--body` to `gh` bypasses the template file, which is why it has to be read and filled
|
||||
in explicitly.
|
||||
|
||||
House style on top of the template: keep each section terse, 1-3 bullet points for the overview
|
||||
and a single sentence of motivation. Add a `**Test case:**` line at the end giving brief steps
|
||||
to verify the change — not part of the template, but reviewers expect it. No fluff.
|
||||
|
||||
5. **Show the draft title and body to the user, and ask whether to open it as a draft PR or as
|
||||
ready for review.** Wait for both answers before anything is published — never assume either.
|
||||
Draft suits work that is still moving, wants early CI feedback, or needs discussion before
|
||||
reviewers spend time on it; ready for review suits a change that is complete and tested.
|
||||
|
||||
6. **Confirm the fork before pushing anything.** `origin` is not guaranteed to be the user's fork,
|
||||
and pushing to the wrong remote is awkward to undo, so establish this before the push rather
|
||||
than after. Derive the head explicitly too — a checkout commonly has several remotes, including
|
||||
other people's forks, and a head inferred by `gh` can point at the wrong one.
|
||||
|
||||
```bash
|
||||
BRANCH=$(git branch --show-current)
|
||||
FORK_OWNER=$(printf '%s' "$(git remote get-url --push origin)" \
|
||||
| sed -E 's#\.git$##; s#^[a-zA-Z+]+://##; s#^[^@/]+@##;
|
||||
s#^[^/:]+(:[0-9]+)?/##; s#^[^/:]+:##; s#/[^/]*$##')
|
||||
```
|
||||
|
||||
Use `--push`: a remote can carry a separate `pushurl`, and it is the push URL the branch
|
||||
actually lands on, so the head must be derived from the same URL `git push` will use.
|
||||
|
||||
This handles the `https://`, `ssh://` and `git@host:owner/repo` forms, with or without an
|
||||
explicit port. Check the result before using it: if `$FORK_OWNER` is empty or still contains
|
||||
`/`, `:` or `@`, the URL was not in a form this understands — stop and report it rather than
|
||||
building a malformed `--head`.
|
||||
|
||||
Show `$FORK_OWNER` to the user and confirm it is the fork the pull request should come from.
|
||||
|
||||
7. **Publish the branch** with `git push -u origin "$BRANCH"`. Do this every time, not only when
|
||||
the branch lacks an upstream — a branch that already tracks `origin` can still hold local
|
||||
commits that have not been pushed, and those would be missing from the pull request.
|
||||
|
||||
The push must succeed before continuing. If it fails, stop and report the error; do not open a
|
||||
pull request against a branch whose commits are not on the fork.
|
||||
|
||||
8. **Open the PR** against upstream, adding `--draft` if that is what the user chose:
|
||||
|
||||
```bash
|
||||
gh pr create --repo Mudlet/Mudlet --base development \
|
||||
--head "${FORK_OWNER}:${BRANCH}" \
|
||||
--title "Fix: <short non-technical title>" \
|
||||
--body "$(cat <<'EOF'
|
||||
<the body from step 4>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
A draft can be marked ready later with `gh pr ready <number>`, so choosing draft is the
|
||||
reversible option.
|
||||
|
||||
9. **Report the result** — the PR URL on success, the error output on failure.
|
||||
|
||||
## Notes
|
||||
|
||||
- Before a human signs off on AI-assisted work they must have built and manually tested it; see
|
||||
the commit-trailer policy in `docs/ai-instructions.md`. Do not fabricate a `Signed-off-by`.
|
||||
- Never force-push to a remote branch.
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
description: Create a PR with Mudlet's template format
|
||||
allowed-tools: Bash, Read, Glob, Grep
|
||||
---
|
||||
|
||||
Create a pull request for the current branch. Follow these steps:
|
||||
|
||||
1. Run `git log development..HEAD --oneline` and `git diff development...HEAD` to understand all changes
|
||||
2. Determine the appropriate title prefix:
|
||||
- `add:` for new user-facing features
|
||||
- `improve:` for enhancements to existing user-facing features
|
||||
- `fix:` for bug fixes visible to users
|
||||
- `infrastructure:` for internal/non-player-visible changes (refactoring, build system, code cleanup, developer tooling)
|
||||
3. Write a title that a non-technical user can understand (appears in changelogs)
|
||||
|
||||
Create the PR using `gh pr create` with this exact template format:
|
||||
|
||||
```
|
||||
gh pr create --title "<prefix>: <short non-technical title>" --body "$(cat <<'EOF'
|
||||
#### Brief overview of PR changes/additions
|
||||
<1-3 terse bullet points describing what changed>
|
||||
|
||||
#### Motivation for adding to Mudlet
|
||||
<1 sentence explaining why this change matters>
|
||||
|
||||
#### Other info (issues closed, discussion etc)
|
||||
<Reference any issues with "Fixes #123" or "Closes #123" if applicable>
|
||||
|
||||
**Test case:** <Brief steps to verify the change works>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
Keep all descriptions terse and to the point. No fluff.
|
||||
1
.claude/skills
Symbolic link
1
.claude/skills
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../.agents/skills
|
||||
58
.github/skills/open-pr/SKILL.md
vendored
58
.github/skills/open-pr/SKILL.md
vendored
|
|
@ -1,58 +0,0 @@
|
|||
---
|
||||
name: open-pr
|
||||
description: >-
|
||||
Publish the current branch and open a pull request to the upstream Mudlet repository.
|
||||
Generates a concise, non-technical PR title and description following the project template.
|
||||
argument-hint: Optional hint about what this PR does (e.g. "adds shimmer blink effect")
|
||||
user-invocable: true
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when the user asks to open a pull request, create a PR, or push their changes upstream. The skill publishes the current branch if needed and opens a PR against the upstream `development` branch.
|
||||
|
||||
## Procedure
|
||||
|
||||
1. **Gather context**: Run `git diff upstream/development...HEAD` to understand what changed. Also run `git log upstream/development..HEAD --oneline` for commit messages and `git branch --show-current` for the branch name.
|
||||
|
||||
2. **Determine the PR title prefix** based on the nature of the changes:
|
||||
- `Fix: ` — for bug fixes
|
||||
- `Improve: ` — for enhancements to existing functionality
|
||||
- `Add: ` — for new features or capabilities
|
||||
- `Infrastructure: ` — for build system, CI, tooling, or project configuration changes
|
||||
|
||||
3. **Generate the PR title**: After the prefix, write a short, non-technical summary that anyone can understand. This title appears in PTB changelogs.
|
||||
|
||||
4. **Generate the PR body** using this exact template format:
|
||||
|
||||
```
|
||||
#### Brief overview of PR changes/additions
|
||||
|
||||
<1-3 sentences summarizing what changed, written for a non-technical audience>
|
||||
|
||||
#### Motivation for adding to Mudlet
|
||||
|
||||
<1-2 sentences explaining why this change is valuable>
|
||||
|
||||
#### Other info (issues closed, discussion etc)
|
||||
|
||||
<Any related issues, discussions, or notes — or "None" if not applicable>
|
||||
```
|
||||
|
||||
5. **Show the draft title and body to the user** and ask for confirmation before proceeding.
|
||||
|
||||
6. **Publish the branch** if it has not been pushed to the user's fork yet:
|
||||
- Run `git push -u origin <branch-name>` to push and set the upstream tracking branch.
|
||||
|
||||
7. **Open the pull request** using the `mcp_github_create_pull_request` tool:
|
||||
- `owner`: `Mudlet`
|
||||
- `repo`: `Mudlet`
|
||||
- `base`: `development`
|
||||
- `head`: `<fork-owner>:<branch-name>` (e.g. `mpconley:feature/my-branch`)
|
||||
- `title`: The generated PR title
|
||||
- `body`: The generated PR body
|
||||
|
||||
To determine `<fork-owner>`, parse it from the `origin` remote URL.
|
||||
|
||||
8. **Report the result**: Show the user the PR URL on success, or the error details on failure.
|
||||
228
CMakePresets.json
Normal file
228
CMakePresets.json
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
{
|
||||
"version": 6,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 25,
|
||||
"patch": 1
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "variant",
|
||||
"hidden": true,
|
||||
"inherits": "base",
|
||||
"binaryDir": "${sourceDir}/build-${presetName}"
|
||||
},
|
||||
{
|
||||
"name": "macos-debug",
|
||||
"displayName": "macOS Debug (Ninja, AddressSanitizer)",
|
||||
"inherits": "base",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-debug-nosan",
|
||||
"displayName": "macOS Debug, no sanitizers (fastest build and run)",
|
||||
"inherits": ["variant", "macos-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-debug-tsan",
|
||||
"displayName": "macOS Debug, ThreadSanitizer",
|
||||
"inherits": ["variant", "macos-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": "Thread"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-debug-ubsan",
|
||||
"displayName": "macOS Debug, UndefinedBehaviorSanitizer",
|
||||
"inherits": ["variant", "macos-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": "Undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-static-analysis",
|
||||
"displayName": "macOS Debug with clang-tidy and cppcheck",
|
||||
"inherits": ["variant", "macos-debug"],
|
||||
"cacheVariables": {
|
||||
"ENABLE_STATIC_ANALYSIS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug",
|
||||
"displayName": "Linux Debug (Ninja, AddressSanitizer)",
|
||||
"inherits": "base",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug-nosan",
|
||||
"displayName": "Linux Debug, no sanitizers (fastest build and run)",
|
||||
"inherits": ["variant", "linux-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug-tsan",
|
||||
"displayName": "Linux Debug, ThreadSanitizer",
|
||||
"inherits": ["variant", "linux-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": "Thread"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-debug-ubsan",
|
||||
"displayName": "Linux Debug, UndefinedBehaviorSanitizer",
|
||||
"inherits": ["variant", "linux-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": "Undefined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-static-analysis",
|
||||
"displayName": "Linux Debug with clang-tidy and cppcheck",
|
||||
"inherits": ["variant", "linux-debug"],
|
||||
"cacheVariables": {
|
||||
"ENABLE_STATIC_ANALYSIS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-lowspec",
|
||||
"displayName": "Linux Debug for low-memory machines (Raspberry Pi and similar)",
|
||||
"inherits": ["variant", "linux-debug"],
|
||||
"cacheVariables": {
|
||||
"USE_SANITIZER": "",
|
||||
"USE_UPDATER": "OFF",
|
||||
"USE_3DMAPPER": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-debug",
|
||||
"displayName": "Windows Debug (MSYS2, Ninja)",
|
||||
"inherits": "base",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_PREFIX_PATH": "$env{MSYSTEM_PREFIX}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "on-macos",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "on-linux",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{ "name": "macos-debug", "inherits": "on-macos", "configurePreset": "macos-debug" },
|
||||
{ "name": "macos-debug-nosan", "inherits": "on-macos", "configurePreset": "macos-debug-nosan" },
|
||||
{ "name": "macos-debug-tsan", "inherits": "on-macos", "configurePreset": "macos-debug-tsan" },
|
||||
{ "name": "macos-debug-ubsan", "inherits": "on-macos", "configurePreset": "macos-debug-ubsan" },
|
||||
{ "name": "macos-static-analysis", "inherits": "on-macos", "configurePreset": "macos-static-analysis" },
|
||||
{ "name": "linux-debug", "inherits": "on-linux", "configurePreset": "linux-debug" },
|
||||
{ "name": "linux-debug-nosan", "inherits": "on-linux", "configurePreset": "linux-debug-nosan" },
|
||||
{ "name": "linux-debug-tsan", "inherits": "on-linux", "configurePreset": "linux-debug-tsan" },
|
||||
{ "name": "linux-debug-ubsan", "inherits": "on-linux", "configurePreset": "linux-debug-ubsan" },
|
||||
{ "name": "linux-static-analysis", "inherits": "on-linux", "configurePreset": "linux-static-analysis" },
|
||||
{
|
||||
"name": "linux-lowspec",
|
||||
"inherits": "on-linux",
|
||||
"configurePreset": "linux-lowspec",
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "windows-debug",
|
||||
"configurePreset": "windows-debug",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "test-defaults",
|
||||
"hidden": true,
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "on-macos",
|
||||
"hidden": true,
|
||||
"inherits": "test-defaults",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "on-linux",
|
||||
"hidden": true,
|
||||
"inherits": "test-defaults",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{ "name": "macos-debug", "inherits": "on-macos", "configurePreset": "macos-debug" },
|
||||
{ "name": "macos-debug-nosan", "inherits": "on-macos", "configurePreset": "macos-debug-nosan" },
|
||||
{ "name": "macos-debug-tsan", "inherits": "on-macos", "configurePreset": "macos-debug-tsan" },
|
||||
{ "name": "macos-debug-ubsan", "inherits": "on-macos", "configurePreset": "macos-debug-ubsan" },
|
||||
{ "name": "macos-static-analysis", "inherits": "on-macos", "configurePreset": "macos-static-analysis" },
|
||||
{ "name": "linux-debug", "inherits": "on-linux", "configurePreset": "linux-debug" },
|
||||
{ "name": "linux-debug-nosan", "inherits": "on-linux", "configurePreset": "linux-debug-nosan" },
|
||||
{ "name": "linux-debug-tsan", "inherits": "on-linux", "configurePreset": "linux-debug-tsan" },
|
||||
{ "name": "linux-debug-ubsan", "inherits": "on-linux", "configurePreset": "linux-debug-ubsan" },
|
||||
{ "name": "linux-static-analysis", "inherits": "on-linux", "configurePreset": "linux-static-analysis" },
|
||||
{ "name": "linux-lowspec", "inherits": "on-linux", "configurePreset": "linux-lowspec" },
|
||||
{
|
||||
"name": "windows-debug",
|
||||
"inherits": "test-defaults",
|
||||
"configurePreset": "windows-debug",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -4,6 +4,13 @@
|
|||
|
||||
Mudlet is a cross-platform MUD client built with Qt6 and C++20, providing scripting capabilities in Lua 5.1. The project emphasizes "powerful simplicity" - clean interface with deep customization options.
|
||||
|
||||
## Skills
|
||||
|
||||
Task-specific instructions live in `.agents/skills/<name>/SKILL.md`, in the [Agent Skills](https://agentskills.io) format. Claude Code, GitHub Copilot and Cursor all read this directory (Claude Code via the `.claude/skills` symlink). Read the relevant one before starting that kind of task rather than working from memory:
|
||||
|
||||
- `build-mudlet` - building, rebuilding or running Mudlet on any platform
|
||||
- `open-pr` - publishing a branch and opening a pull request upstream
|
||||
|
||||
## Coding standards
|
||||
All files should end with a newline character at the end of the file.
|
||||
|
||||
|
|
@ -131,10 +138,11 @@ To demonstrate a bug fix or UI change with a screen recording, follow the before
|
|||
|
||||
## Build system notes
|
||||
|
||||
- **Before running any `cmake`, `ninja` or `make` command, read the `build-mudlet` skill in `.agents/skills/build-mudlet/SKILL.md`.** It carries the per-platform invocation and the parallelism pitfalls; an unbounded build command can saturate the machine's memory.
|
||||
- **Build system**: CMake (handles platform-specific configurations). See https://wiki.mudlet.org/w/Compiling_Mudlet for instructions.
|
||||
- Check code quality with clang-tidy using `.clang-tidy` configuration file
|
||||
- Allow up to 10mins for a build - it can take a while
|
||||
- Building on macOS or Windows, and compile-time debugging defines: see `docs/platform-builds.md`
|
||||
- Platform specifics and compile-time debugging defines: see `docs/platform-builds.md`
|
||||
|
||||
### Code formatting
|
||||
|
||||
|
|
@ -170,21 +178,22 @@ Before the human signs off, they must have built and manually tested the change
|
|||
|
||||
Both trailers go at the end of the commit message. Apply this to every AI-assisted commit, not just the first. See the "AI Coding Assistants" section in `docs/CONTRIBUTING.md` for the full policy.
|
||||
|
||||
### Building on Linux
|
||||
### Building
|
||||
|
||||
For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet
|
||||
|
||||
Build through a preset from `CMakePresets.json`. Run `cmake --list-presets` to see the ones offered
|
||||
on the current machine — the listing is filtered by host system, so only that platform's presets
|
||||
appear. Read the `build-mudlet` skill for the per-platform detail:
|
||||
|
||||
```bash
|
||||
# cd to the right build directory
|
||||
cd /path/to/Mudlet/build
|
||||
|
||||
# configure (only needed the first time)
|
||||
cmake ../ -G Ninja
|
||||
|
||||
# Compile using this command and wait up to 10mins for a build. Cmake runs the build in parallel by default, no need to specify number of jobs:
|
||||
cmake --build .
|
||||
# from the repository root; wait up to 10mins for a full build
|
||||
cmake --preset linux-debug
|
||||
cmake --build --preset linux-debug
|
||||
|
||||
# Run Mudlet - it's a visual, desktop application
|
||||
cd /path/to/Mudlet/build
|
||||
./src/mudlet
|
||||
./build/src/mudlet # macOS: ./build/src/mudlet.app/Contents/MacOS/mudlet
|
||||
```
|
||||
|
||||
Variant presets such as `linux-debug-nosan` build into `build-<preset-name>/`, so the binary is
|
||||
under that directory rather than `build/`.
|
||||
|
|
|
|||
|
|
@ -7,20 +7,88 @@ For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet
|
|||
**Essential build commands:**
|
||||
|
||||
```bash
|
||||
# Build
|
||||
cd /path/to/Mudlet/build
|
||||
# wait up to 10mins for a build
|
||||
cmake ../../Mudlet -DCMAKE_PREFIX_PATH=`brew --prefix qt6`
|
||||
make -j `sysctl -n hw.ncpu`
|
||||
cd /path/to/Mudlet
|
||||
# wait up to 10mins for a full build
|
||||
cmake --preset macos-debug
|
||||
cmake --build --preset macos-debug
|
||||
|
||||
# Run Mudlet - use absolute path to avoid directory confusion
|
||||
/path/to/Mudlet/build/src/mudlet.app/Contents/MacOS/mudlet
|
||||
# Run Mudlet
|
||||
./build/src/mudlet.app/Contents/MacOS/mudlet
|
||||
```
|
||||
|
||||
Run `cmake --list-presets` to see the presets available on your machine; alongside `macos-debug`
|
||||
there are `-nosan`, `-tsan` and `-ubsan` variants and a `macos-static-analysis` preset. Variants
|
||||
build into `build-<preset-name>/` rather than `build/`, so several configurations can coexist
|
||||
without invalidating each other.
|
||||
|
||||
The presets do not pin a Qt location, relying on CMake's default search path. If Qt is not found,
|
||||
pass it explicitly: `cmake --preset macos-debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt6)"`.
|
||||
|
||||
**Do not use `cmake --build . --parallel` without a job count in a Makefiles build tree.** A bare
|
||||
`--parallel` passes `-j` with no number to make, which imposes no limit on concurrent jobs; make
|
||||
will start as many compilers as the dependency graph allows, exhausting RAM and swap and finishing
|
||||
slower than a bounded build. Ninja, which the presets use, defaults to a bounded job count. In an
|
||||
existing Makefiles tree, use `make -j $(sysctl -n hw.ncpu)`.
|
||||
|
||||
ccache is enabled automatically whenever it is installed. A full cache evicts objects continuously,
|
||||
so branch switches can trigger near-full rebuilds — run `ccache -s`, and if `Cache size` has
|
||||
reached `Max cache size`, raise it with `ccache -M <n>G`.
|
||||
|
||||
## Building on Windows
|
||||
|
||||
For complete setup instructions, see: https://wiki.mudlet.org/w/Compiling_Mudlet#Compiling_on_Windows
|
||||
|
||||
Builds run under MSYS2, in the **CLANG64** environment — open a CLANG64 shell, not MINGW64, and
|
||||
check it is a real MSYS2 shell rather than Git for Windows' bash carrying an inherited `MSYSTEM`
|
||||
(`MSYSTEM_PREFIX` is empty in the latter). `CI/setup-windows-sdk.sh` and
|
||||
`CI/build-mudlet-for-windows.sh` exit with an error on any other `MSYSTEM`, including the
|
||||
`CLANGARM64` environment native to ARM64 hosts.
|
||||
|
||||
The `windows-debug` preset reads `MSYSTEM_PREFIX`, which MSYS2 sets in each of its shells, so the
|
||||
preset follows whichever environment is provisioned:
|
||||
|
||||
```bash
|
||||
cmake --preset windows-debug
|
||||
cmake --build --preset windows-debug
|
||||
```
|
||||
|
||||
Sanitizers are not enabled on Windows (`src/CMakeLists.txt` guards them with `if(NOT WIN32)`),
|
||||
so there is no `-nosan` variant.
|
||||
|
||||
## Sanitizers and static analysis
|
||||
|
||||
Sanitizers are enabled on every non-Windows build; `USE_SANITIZER` defaults to `address`. Use the
|
||||
`-tsan` / `-ubsan` / `-nosan` presets to change that, or pass a CMake list — semicolon-separated,
|
||||
not comma-separated — such as `-DUSE_SANITIZER="Address;Undefined"`. A comma-separated value is
|
||||
read as a single name, which silently skips the per-sanitizer options such as
|
||||
`-fno-omit-frame-pointer`.
|
||||
|
||||
Usable names are `Address`, `Thread` and `Undefined` on macOS, plus `Memory` and `Leak` on Linux.
|
||||
`MemoryWithOrigins` appears in the `USE_SANITIZER` cache docstring but has no mapping declared in
|
||||
`src/cmake/EnableSanitizers.cmake`, so it always fails. An unavailable or incompatible selection
|
||||
raises a `SEND_ERROR`: configure finishes, but generation is blocked.
|
||||
|
||||
Static analysis (clang-tidy and cppcheck) runs during compilation with the
|
||||
`<platform>-static-analysis` presets, which set `ENABLE_STATIC_ANALYSIS=ON`. The two tools are
|
||||
independent — whichever is on `PATH` runs. A missing clang-tidy produces a CMake warning, but a
|
||||
missing cppcheck only emits a `STATUS` line, so read the configure output rather than assuming both
|
||||
are active.
|
||||
|
||||
Because IDEs read `CMakePresets.json` natively, selecting one of these presets in CLion, VS Code or
|
||||
Qt Creator is enough — no per-IDE sanitizer configuration is needed.
|
||||
|
||||
## Optional feature modules
|
||||
|
||||
Six feature modules are declared through `include_optional_module` in `CMakeLists.txt`: the updater,
|
||||
fonts, 3D mapper, shader hot-reloading, memory tracking and the build-type splash screen. Each has a
|
||||
`USE_*` option and a `WITH_*` name, and they are **not** interchangeable — `cmake/IncludeOptionalModule.cmake`
|
||||
reads the `WITH_*` name from the **environment** only. So `-DWITH_UPDATER=NO` on the command line is
|
||||
accepted by CMake and silently ignored; use `-DUSE_UPDATER=OFF`, or set `WITH_UPDATER=NO` in the
|
||||
environment. Note that shader hot-reloading and memory tracking default to OFF, the rest to ON.
|
||||
|
||||
This applies only to those six. Other `WITH_*` names are ordinary options: `WITH_SENTRY` and
|
||||
`SENTRY_SEND_DEBUG` are declared with `option()` and are set on the command line as normal.
|
||||
|
||||
## Debugging options
|
||||
|
||||
`src/CMakeLists.txt` contains commented debugging defines for development (search "Debugging code inclusions"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue