diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3d68ff00..15d7f306 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,15 +1,26 @@ - +## Summary + + + ## Type of change - + - [ ] Minor changes or tweaks (quality of life stuff) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update + +## Notes for reviewer + + + + diff --git a/.gitignore b/.gitignore index aee6e667..39df9edc 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ logs/ *.iws .idea/ +# Eclipse / VS Code Java (Buildship) compile output. +# Only per-module bin/ — the root bin/ holds tracked native libs. +/*/bin/ + # Package Files # *.jar *.war diff --git a/AGENTS.md b/AGENTS.md index 61e22ab5..ad497398 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,9 +16,13 @@ upgrading submodules, and the codegen-internals conventions. The everyday conven - **`.claude/docs/patterns.md`** — recurring patterns when adding to the binding (the codegen loop, annotated stubs, struct wrappers, out-parameter `Im*` wrappers, module boundaries, application lifecycle). -- **`docs/CONTRIBUTING.md`** — PR/commit workflow. Includes the conventional-commit - format and, importantly, the **`Co-authored-by` trailer rule for AI-assisted commits** - and the "you are responsible for the change" rule. Read it before opening a PR. +- **`CONTRIBUTING.md`** — the human-facing contributor guide, and the authority on + everything commit- and release-shaped: the conventional-commit types/scopes tables, PR + title and body rules (PRs are squash-merged, so the **PR title must be a valid commit + header**), label mapping, the versioning scheme (version tracks Dear ImGui, so it can + never signal a break), the release procedure, and — importantly — the **`Co-authored-by` + trailer rule for AI-assisted commits** plus the "you are responsible for the change" + rule. Read it before writing a commit message or opening a PR. If anything below conflicts with those files, the dedicated file wins — update it there, not here. @@ -196,11 +200,28 @@ Use `providers.exec { ... }` for shell-outs, never `.execute()`. Capture resolve ## PR workflow -The full commit-message format, the conventional-commit types/scopes, and the -mandatory `Co-authored-by` trailer for AI-assisted commits are documented in -`docs/CONTRIBUTING.md` — follow that. The rule that submodule bumps, Gradle/deps -bumps, and codegen-tooling changes each go in their own PR is in -`.claude/rules/guardrails.md` ("Don't merge submodule bumps with feature work"). +`CONTRIBUTING.md` is the authority here — follow it, don't paraphrase it: + +- **Commit messages** → "Commit message format". Types (`feat|fix|perf|refactor|docs|test|build|chore|revert`) + and scopes (`api|native|generator|vendor|lwjgl3|app|example|deps|ci|gradle|readme|agents|contributing`) + are fixed tables — pick from them, never invent a scope. `!` in the header requires a + `BREAKING CHANGE:` footer. +- **PR title** → a descriptive prose sentence covering the whole change, sentence case, **no** + `type(scope):` prefix — the type is carried by the label, so apply exactly one from the mapping + table there (one label per commit type; `build(deps)` takes `deps`), plus `breaking-change` on + top whenever the header carries `!`. The conventional header is written into the squash subject + at merge time, not the title. +- **AI-assisted commits** → the `Co-authored-by` trailer is mandatory, family-level model name + only. Strip versioned model names, session URLs, and "Generated with …" lines that tooling + adds by default, and check the trailer survives the squash. +- **Releases** → "Releases". Tag-driven (`git describe` is the version of record), version + tracks Dear ImGui's `MAJOR.MINOR`, so a breaking change is only ever visible via `!`, the + footer, the `breaking-change` label, and the release notes. Never cut a release on stale + `bin/` natives. + +The rule that submodule bumps, Gradle/deps bumps, and codegen-tooling changes each go in their +own PR is in `.claude/rules/guardrails.md` ("Don't merge submodule bumps with feature work") +and restated in `CONTRIBUTING.md` § "Before you start". Operational guidance on top of those: diff --git a/CLAUDE.md b/CLAUDE.md index 20acacc8..8acc30e3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,22 +2,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. -See [AGENTS.md](AGENTS.md) — it is the canonical guidance for AI agents in this repo and covers everything Claude Code -needs: +Read [AGENTS.md](AGENTS.md) — it is the canonical and authoritative guidance for AI agents in this repo, covering +project layout, build & test commands, the codegen workflow, submodule bumps, gotchas, conventions, and the PR process. -- What the repo is (JNI binding for Dear ImGui + extensions, codegen-driven multi-module Gradle build). -- Project layout (`imgui-binding/`, `imgui-lwjgl3/`, `imgui-app/`, `buildSrc/`, `include/` submodules, etc.). -- The **golden rule**: never edit `imgui-binding/src/generated/java/` — it is regenerated from annotated sources in - `imgui-binding/src/main/java/`. Workflow: edit source → `./gradlew :imgui-binding:generateApi` → commit both trees - together. -- Build & test commands (`compileJava`, `javadoc`, `generateApi`, `generateAst`, `generateLibs`, `build`) and the visual - smoke-test flow for backend/font/example changes. -- Submodule-bump procedure for Dear ImGui and extensions, including AST regeneration scope rules. -- Gotchas: doclint-vs-C++ comment patterns, vendor patches, `GenerateLibs.groovy` literal-string rewrites, AST drift, - rebase strategy for codegen output, submodule sync after branch switch, `bin/` ownership by CI. -- Design conventions (dual font loader: stb_truetype + FreeType). -- Codegen-internals conventions for `buildSrc/` (Spoon generic-type bounds, Gradle 9 configuration cache). -- PR workflow and merge-ordering guidance. +The golden rule from there, repeated because it is easy to trip over: **never edit +`imgui-binding/src/generated/java/`** — it is regenerated from annotated sources in `imgui-binding/src/main/java/`. -Treat `AGENTS.md` as authoritative. If something here ever conflicts with `AGENTS.md`, `AGENTS.md` wins — update it -there, not here. +If anything here ever conflicts with `AGENTS.md`, `AGENTS.md` wins — update it there, not here. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..64255e0c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,460 @@ +# Contributing to imgui-java + +Contributions are welcome — bug reports, missing-binding requests, fixes, new binding surface, backend work, and doc +improvements alike. + +This document covers the mechanics: how to build the project, the rules that decide whether a patch is reviewable, the +commit format, the PR flow, and how releases are cut. + +- **Contents** + - [Before you start](#before-you-start) + - [Quick start](#quick-start) + - [Development loop](#development-loop) + - [Commit message format](#commit-message-format) + - [Pull requests](#pull-requests) + - [Releases](#releases) + - [Contributing with AI agents](#contributing-with-ai-agents) + - [Reporting bugs](#reporting-bugs) + - [License](#license) + +## Before you start + +Four rules cause most of the rejected patches in this repo. Read them before writing code. + +### 1. Never edit `imgui-binding/src/generated/java/` + +The Java API is **codegen-driven**. Hand-written annotated stubs live in `imgui-binding/src/main/java/`; the Spoon-based +generator in `buildSrc/` expands them into `imgui-binding/src/generated/java/`. Both trees are committed, but only the +first is a source. Edits to the generated tree are silently reverted on the next `generateApi` run. + +```bash +# edit imgui-binding/src/main/java/... +./gradlew :imgui-binding:generateApi +git add imgui-binding/src/main/java imgui-binding/src/generated/java +``` + +Source and regenerated output belong in the **same commit** — a commit that changes one without the other leaves the +tree inconsistent. + +### 2. Never commit native binaries + +`bin/libimgui-java64.*` and `bin/imgui-java64.dll` are owned by CI. The `update-bin` job rebuilds them on `main` after a +binding change and commits them as `[ci skip] update native binaries`. Locally built natives must not be staged. + +Use `git add ` instead of `git add -A` / `git add .` — bulk staging picks up `bin/` and +`imgui-binding/build/libsNative/` by accident. + +### 3. One topic per pull request + +Submodule bumps, Gradle/dependency bumps, codegen-tooling changes, and new API surface each go in their own PR. A +submodule bump already produces a large regenerated diff; adding a feature on top makes it unreviewable and makes CI +failures ambiguous. Land the bump first, add the new surface in a follow-up. + +### 4. Javadoc must pass doclint + +Doc comments in the binding are copied verbatim from Dear ImGui's C++ headers, and JDK 17's doclint rejects anything +that parses as broken HTML. CI runs javadoc as part of the build; a doc-comment typo fails the whole pipeline. + +Wrap operators in `{@code ...}` — `<`, `>`, `&`, `&&`, `||`, `->` all break otherwise. Keep `@link` targets, `@param`, +and `@return` in sync with the current method signature. + +## Quick start + +```bash +git clone --recurse-submodules https://github.com/SpaiR/imgui-java.git +cd imgui-java +./gradlew :example:run +``` + +Already cloned without submodules, or switched branches? + +```bash +git submodule update --init --recursive +``` + +`git checkout` does **not** update submodules. If `include/*` pointers differ between branches you will compile against +the wrong headers and get mystifying errors. + +**Prerequisites** + +| What | Needed for | Notes | +|-------------------------------|--------------------------------------------------|-----------------------------------------------------------| +| Any recent JDK | Everything | Gradle's toolchain pins JDK 17 and downloads it if missing | +| A C++ toolchain | Rebuilding the native library (`generateLibs`) | Only if you touch JNI or `native` method signatures | +| `clang++` | `./gradlew generateAst` | Only when bumping a submodule | +| `mingw-w64` | Cross-building the Windows native from Linux | CI does this; rarely needed locally | + +Java-only changes run fine against the natives already committed in `bin/` — no C++ toolchain required. + +## Development loop + +### Adding or changing binding API + +```bash +# 1. edit the annotated source +$EDITOR imgui-binding/src/main/java/imgui/ImGui.java + +# 2. regenerate the Java API +./gradlew :imgui-binding:generateApi + +# 3. check +./gradlew :imgui-binding:compileJava +./gradlew :imgui-binding:javadoc +``` + +If you add, rename, remove, or reorder a `native` method, the committed natives no longer match the Java side and you +will get an `UnsatisfiedLinkError` at runtime — static checks will not catch it. Rebuild and smoke-test: + +```bash +buildSrc/scripts/build.sh +cp /tmp/imgui/dst/libimgui-java64. bin/ +./gradlew :example:run -PlibPath=$PWD/bin +``` + +Then **revert the `bin/` copy** before committing (see [rule 2](#2-never-commit-native-binaries)). + +Backend, font, texture, and example changes also need a real run — a blank font atlas or an assertion loop does not show +up in a compile. + +### Checks before you push + +```bash +./gradlew :imgui-binding:compileJava # fastest sanity check +./gradlew check # tests + Checkstyle (imgui-lwjgl3, imgui-app) +./gradlew :imgui-binding:javadoc # zero `error:` lines is the bar +./gradlew buildAll # what CI runs +``` + +Checkstyle runs at `severity="error"` for `imgui-lwjgl3` and `imgui-app`. Fix the code rather than relaxing the rule; if +a rule genuinely does not fit a construct, suppress at the smallest possible scope with `@SuppressWarnings`. Do not add +entries to `config/checkstyle/suppressions.xml`. + +`imgui-binding` ships with **zero runtime dependencies**. Adding one is a breaking change for downstream consumers and +needs sign-off before you write the code. Public modules also compile with `--release 8` — no `List.of`, `var`, +`String.isBlank()`, or other Java 9+ APIs in `imgui-binding`, `imgui-lwjgl3`, or `imgui-app`. + +For deeper background — the codegen internals, the submodule-upgrade procedure, the dual font-loader design — see +[`AGENTS.md`](AGENTS.md). It is written for AI agents but applies equally to humans. + +## Commit message format + +*Adapted from the +[Angular commit message format](https://github.com/angular/angular/blob/92113d73dd38d0285e25e8d678c240cf4aa8834a/CONTRIBUTING.md#commit) +and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).* + +Commit history is a changelog for the next maintainer. Precise messages make it readable. + +``` +
+ + + +