Skip to content

Commit 17db78f

Browse files
committed
Next set of documentation updates.
1 parent 1fb054c commit 17db78f

File tree

7 files changed

+169
-380
lines changed

7 files changed

+169
-380
lines changed

docs/architecture.md

Lines changed: 103 additions & 213 deletions
Large diffs are not rendered by default.

docs/cmake_bindings.md

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,26 @@
11
# CMake Bindings
22

3-
The `CMake` format generates `CMakeLists.txt` and `CMakePresets.json` files for building Rice C++ bindings. This is typically run as a second pass after generating the Rice binding source files.
3+
The `CMake` format generates `CMakeLists.txt` and `CMakePresets.json` files for building Rice C++ bindings. This is run as a second pass after generating the Rice binding source files.
44

5-
## Usage
6-
7-
The CMake format scans the output directory for `*-rb.cpp` files produced by the Rice format and generates:
8-
9-
- **`CMakeLists.txt`** (top-level) - Project configuration with Rice fetching, Ruby detection, and source file listing
10-
- **`CMakeLists.txt`** (per subdirectory) - Source file listing for each subdirectory
11-
- **`CMakePresets.json`** - Build presets for Linux, macOS, MSVC, MinGW, and Clang on Windows (debug and release variants)
5+
Rice supports building extensions with either [extconf.rb](https://ruby-rice.github.io/4.x/packaging/extconf.rb/) or [CMake](https://ruby-rice.github.io/4.x/packaging/cmake/). While `extconf.rb` works for simple bindings, CMake is vastly superior for anything more complex — it provides better cross-platform support, dependency management, and build configuration.
126

137
## Configuration
148

159
```yaml
1610
format: CMake
1711
extension: my_extension
1812

19-
# CMake expressions for target_include_directories
2013
include_dirs:
2114
- "${CMAKE_CURRENT_SOURCE_DIR}/../headers"
2215
```
2316
24-
### Options
25-
26-
| Option | Description |
27-
|--------|-------------|
28-
| `extension` | Project name used in `project()` and target name. Required. |
29-
| `include_dirs` | List of include directory expressions added via `target_include_directories`. These are written directly into CMakeLists.txt, so CMake variables like `${CMAKE_CURRENT_SOURCE_DIR}` work. |
30-
31-
## Generated CMakeLists.txt
17+
See [configuration](configuration.md) for details on all options.
3218
33-
The top-level `CMakeLists.txt` includes:
34-
35-
- C++17 standard requirement
36-
- Rice fetched from GitHub via `FetchContent`
37-
- Ruby detection via `find_package(Ruby)`
38-
- Library target (SHARED on MSVC, MODULE elsewhere)
39-
- Extension output configuration (correct suffix, visibility settings)
40-
- All `*-rb.cpp` source files
41-
42-
## Workflow
19+
## Usage
4320
4421
Generate bindings in two passes:
4522
4623
```bash
47-
# Ensure output directory exists
48-
mkdir -p /path/to/output
49-
5024
# 1. Generate Rice C++ source files
5125
ruby-bindgen rice_config.yaml
5226

@@ -62,9 +36,41 @@ cmake --preset linux-debug # or msvc-debug, macos-debug, etc.
6236
cmake --build build/linux-debug
6337
```
6438

65-
## Build Presets
39+
## Output
40+
41+
The CMake format scans the output directory for `*-rb.cpp` files and generates:
42+
43+
``` mermaid
44+
flowchart LR
45+
subgraph Input
46+
CF["cmake_config.yaml"]
47+
S1["*-rb.cpp"]
48+
end
49+
50+
CF & S1 --> RB["ruby-bindgen"]
51+
52+
subgraph "CMake Output"
53+
C1["CMakeLists.txt"]
54+
C2["CMakePresets.json"]
55+
end
56+
57+
RB --> C1 & C2
58+
```
59+
60+
### Top Level
6661

67-
The generated `CMakePresets.json` includes presets for all major platforms:
62+
The top-level `CMakeLists.txt` is a complete project file that configures the entire build:
63+
64+
- C++17 standard requirement
65+
- Rice fetched from GitHub via `FetchContent`
66+
- Ruby detection via `find_package(Ruby)`
67+
- Library target (SHARED on MSVC, MODULE elsewhere)
68+
- Extension output configuration (correct suffix, visibility settings)
69+
- Subdirectory includes and `*-rb.cpp` source file listing
70+
71+
For a well-documented example, see the [BitmapPlusPlus-ruby CMakeLists.txt](https://github.com/ruby-rice/BitmapPlusPlus-ruby/blob/main/ext/CMakeLists.txt). For details on how Rice uses CMake, see the Rice [CMake](https://ruby-rice.github.io/4.x/packaging/cmake/) documentation.
72+
73+
The top-level directory also gets a `CMakePresets.json` with build presets for all major platforms. For an example, see the [BitmapPlusPlus-ruby CMakePresets.json](https://github.com/ruby-rice/BitmapPlusPlus-ruby/blob/main/ext/CMakePresets.json). For details, see the Rice [CMakePresets.json](https://ruby-rice.github.io/4.x/packaging/cmake/#cmakepresetsjson) documentation.
6874

6975
| Preset | Platform | Compiler |
7076
|--------|----------|----------|
@@ -74,4 +80,19 @@ The generated `CMakePresets.json` includes presets for all major platforms:
7480
| `mingw-debug` / `mingw-release` | Windows | MinGW GCC |
7581
| `clang-windows-debug` / `clang-windows-release` | Windows | clang-cl |
7682

77-
All presets use Ninja as the build generator and include appropriate compiler flags for each platform (visibility settings, debug info, optimization levels).
83+
All presets use [Ninja](https://ninja-build.org/) as the build generator and include appropriate compiler flags for each platform (visibility settings, debug info, optimization levels).
84+
85+
### Subdirectories
86+
87+
Each subdirectory containing `*-rb.cpp` files gets a minimal `CMakeLists.txt` that lists its source files and any nested subdirectories:
88+
89+
```cmake
90+
# Subdirectories
91+
add_subdirectory("hal")
92+
93+
# Sources
94+
target_sources(${CMAKE_PROJECT_NAME} PUBLIC
95+
"matrix-rb.cpp"
96+
"image-rb.cpp"
97+
)
98+
```

docs/cpp/buffers.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,3 @@ void getMinMax(double* min, double* max); // Out parameters via ArgBuffer
1010
int* createBuffer(int size); // ReturnBuffer
1111
void processArrays(float** matrices, int count); // Double pointer via ArgBuffer
1212
```
13-
14-
This enables Ruby code to:
15-
- Pass buffers of data to C++ functions
16-
- Use out parameters for returning values
17-
- Work with arrays of pointers

docs/cpp/iterators.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,6 @@ namespace std
8989
}
9090
```
9191

92-
### How It Works
93-
94-
`ruby-bindgen` detects incomplete iterators by:
95-
96-
1. Checking if the iterator class defines the required typedefs (`value_type`, `reference`, `pointer`, `difference_type`, `iterator_category`)
97-
2. If any are missing, it infers the types from the iterator's `operator*()` return type
98-
3. The generated traits specialization is placed at the top of the output file, before the Rice bindings code
99-
100-
### Const Iterators
101-
102-
`ruby-bindgen` also detects const iterators by examining the `operator*()` return type. If it returns a const reference, the generated `reference` typedef will be `const T&` instead of `T&`.
103-
10492
## Examples
10593

10694
See [test/headers/cpp/iterators.hpp](../test/headers/cpp/iterators.hpp) for example iterator classes, including both complete and incomplete iterators. The generated bindings are in [test/bindings/cpp/iterators-rb.cpp](../test/bindings/cpp/iterators-rb.cpp).

docs/limitations.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ This page summarizes current limitations and constraints in `ruby-bindgen`.
77
- Correct parsing depends on accurate `clang`/`clang-cl` include and language arguments.
88
- Some libraries still require manual post-generation adjustments.
99

10-
## C++ (Rice) Generation
10+
## Rice Generation
1111

12-
- Generated code is not guaranteed to compile without manual fixes for all libraries.
12+
- Generated code may not compile without manual fixes.
1313
- Default argument reconstruction is heuristic and can fail for complex C++ expressions.
1414
- Some APIs need explicit skipping via `skip_symbols` to avoid compile/link failures.
1515
- Functions/methods with unsupported signatures may be skipped (for example variadic callables).
@@ -23,13 +23,4 @@ This page summarizes current limitations and constraints in `ruby-bindgen`.
2323

2424
## FFI Generation
2525

26-
- Intended for C APIs. C++ class semantics are not represented in FFI output.
2726
- Runtime loading depends on correct `library_names` / `library_versions` and system loader paths.
28-
29-
## Scope
30-
31-
`ruby-bindgen` optimizes for automating most wrapping work, then letting users handle edge cases via:
32-
33-
- configuration filters (`skip`, `skip_symbols`, `export_macros`)
34-
- refinement files
35-
- targeted manual updates for problematic generated code

docs/prior_art.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,12 @@ This page lists related projects and adjacent tools that influenced, overlap wit
1010
- Scope: Multi-language binding generator for C and C++
1111
- Notes: Generates bindings for many languages including Ruby, Python, Java, and Go. Uses its own interface definition files rather than parsing headers directly. The most established tool in this space — active since 1996.
1212

13-
## C
14-
1513
### ffi_gen
1614

1715
- Project: [ffi_gen](https://github.com/ffi/ffi_gen)
1816
- Scope: Generate Ruby FFI wrappers for C APIs
1917
- Notes: Has not been updated in over a decade and includes liblang findings versus using [ffi-clang](https://github.com/ioquatix/ffi-clang).
2018

21-
## C++
22-
2319
### rbind
2420

2521
- Project: [rbind](https://github.com/D-Alex/rbind)

docs/updating_bindings.md

Lines changed: 10 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,29 @@
22

33
After generating bindings with `ruby-bindgen`, you'll need to regenerate them periodically as the upstream library evolves, `ruby-bindgen` improves, or you upgrade dependencies. This document covers strategies for managing that process.
44

5-
All examples below reference the [opencv-ruby](https://github.com/ruby-rice/opencv-ruby) project, which wraps OpenCV's ~350 generated files and is a good real-world reference.
5+
## Simple Case
66

7-
## Regenerate and Done
8-
9-
The best case. Run `ruby-bindgen` again and the new output compiles and works:
7+
If you have no [customizations](cpp/customizing.md) to preserve, then you can simply regenerate the bindings:
108

119
```bash
1210
ruby-bindgen bindings.yaml
1311
```
1412

15-
This works when:
16-
- You're updating `ruby-bindgen` (bug fixes, new features) and don't have manual changes
17-
- The upstream library's API didn't change in ways that break compilation
18-
- Your bindings are simple enough that `ruby-bindgen` handles everything
13+
In most cases, the updated bindings should compile and work.
1914

20-
If this is your situation, you're done. The sections below are for when you have [customizations](cpp/customizing.md) that need to be preserved across regenerations.
15+
The rest of this page discusses strategies for more complex cases where you want to preserve [customizations](cpp/customizing.md) when regenerating bindings.
2116

2217
## Preserving Refinements
2318

24-
[Refinements](cpp/customizing.md#refinements-separate-manual-code) live in a separate directory that `ruby-bindgen` never touches. They survive regeneration automatically - no action needed.
19+
[Refinements](cpp/customizing.md#refinements-separate-manual-code) live in a separate directory that `ruby-bindgen` never touches, so the source files survive regeneration automatically. However, the top-level `-rb.cpp` file is regenerated, so you will need to re-add the `#include` directives and `Init_*_Refinement` calls.
2520

2621
## Preserving Manual Edits
2722

28-
If you have [manual edits](cpp/customizing.md#manual-edits) to generated files, you need a way to reapply them after regeneration. There are two approaches:
23+
If you have [manual edits](cpp/customizing.md#manual-edits) to generated files, you need a way to reapply them after regeneration. Two possible approaches include:
2924

3025
### Option A: Diff File
3126

32-
Maintain a unified diff file that can be reapplied after regeneration:
27+
Maintain a diff file that can be reapplied after regeneration:
3328

3429
```bash
3530
# After making all manual changes to generated files
@@ -51,98 +46,11 @@ git apply manual_updates.diff
5146

5247
**Cons**: Diffs are fragile. If `ruby-bindgen`'s output changes line numbers or formatting, the diff won't apply cleanly. You'll need to manually resolve failures and regenerate the diff.
5348

54-
### Option B: Instruction File
55-
56-
Maintain a structured document (`manual_updates.md`) that describes each change declaratively. An AI assistant or a human can follow the instructions after each regeneration.
57-
58-
Here's how opencv-ruby structures its `manual_updates.md`:
59-
60-
#### Missing Includes
61-
62-
A table mapping files to required manual includes:
63-
64-
```markdown
65-
## Manual Includes
66-
67-
| File | Manual Includes |
68-
|------------------------------------------|----------------------------------------------------------|
69-
| `opencv2/core/bindings_utils-rb.cpp` | `<opencv2/core.hpp>` |
70-
| `opencv2/core/mat-rb.cpp` | `<opencv2/core/cuda.hpp>`, `<opencv2/core/opengl.hpp>` |
71-
| `opencv2/core/saturate-rb.cpp` | `<algorithm>`, `<climits>` |
72-
| `opencv2/flann/flann_base-rb.cpp` | `<opencv2/core/base.hpp>`, `<opencv2/flann/defines.h>` |
73-
```
74-
75-
#### Namespace Cleanup
76-
77-
```markdown
78-
## DNN Module
79-
80-
| File | Change |
81-
|------------------------------------------|----------------------------------------------------------|
82-
| `opencv2/dnn/*.cpp`, `opencv2/dnn/*.hpp` | Replace `::dnn4_v\d+` with empty string |
83-
| `opencv2/dnn/*.cpp`, `opencv2/dnn/*.hpp` | Replace `Dnn4V\d+` with empty string in variable names |
84-
| `opencv2/dnn/*.cpp` | Delete `Module rb_mCvDnn = define_module_under(..., "");` |
85-
```
86-
87-
#### Version Guards
88-
89-
Specific line ranges to wrap with `#if` guards:
90-
91-
```markdown
92-
## OpenCV Version Guards
93-
94-
### `opencv2/core/bindings_utils-rb.cpp`
95-
- **Line ~38**: `dump_int64` (>= 407)
96-
- **Line ~113**: `dump_vec2i` through `ClassWithKeywordProperties` (>= 407)
97-
- **Line ~124**: `FunctionParams` class (>= 408)
49+
### Option B: Agent File
9850

99-
### `opencv2/core/cvdef-rb.cpp`
100-
- **Line ~73**: `CV_CPU_NEON_DOTPROD` constant (>= 407)
101-
- **Line ~77**: `CV_CPU_NEON_FP16`, `CV_CPU_NEON_BF16` constants (>= 409)
102-
```
51+
Maintain a structured document (`manual_updates.md`) that describes each change declaratively. An AI assistant or a human can follow the instructions after each regeneration. For an example, see opencv-ruby's [manual_updates.md](https://github.com/ruby-rice/opencv-ruby/blob/main/ext/manual_updates.md).
10352

10453
**Pros**: Survives large formatting changes, human-readable, an AI assistant can apply the instructions even when line numbers shift.
10554

106-
**Cons**: Requires more effort to write initially. Must be kept in sync with actual changes.
107-
108-
### Combining Both Approaches
109-
110-
opencv-ruby maintains both files:
111-
112-
- `manual_updates.md` - the authoritative description of what changes are needed and why
113-
- `manual_updates.diff` - a snapshot of the actual changes for quick verification
114-
115-
After regeneration:
116-
1. Try applying the diff (`git apply manual_updates.diff`)
117-
2. If it fails, use `manual_updates.md` as a guide (manually or with AI)
118-
3. After all changes are applied, regenerate the diff:
119-
```bash
120-
git diff -- ext/ ':(exclude)ext/manual_updates.md' > ext/manual_updates.diff
121-
```
122-
123-
## Recommended Workflow
124-
125-
For ongoing maintenance after an upstream library update:
126-
127-
```bash
128-
# 1. Regenerate
129-
ruby-bindgen bindings.yaml
130-
131-
# 2. Try building
132-
cmake --preset linux-debug && cmake --build build/linux-debug
133-
134-
# 3. If it compiles, done. If not:
135-
# - Missing includes? Add to manual_updates.md and apply
136-
# - Linker errors? Comment out and document
137-
# - New API version issues? Add version guards
138-
# - Need custom methods? Add to refinements/
139-
140-
# 4. Update the diff file
141-
git diff -- ext/ ':(exclude)ext/manual_updates.md' > ext/manual_updates.diff
142-
```
143-
144-
## Tips
55+
**Cons**: Must be kept in sync with actual changes.
14556

146-
- **Keep `manual_updates.md` up to date** - it's the source of truth when diffs fail to apply
147-
- **Refinements survive automatically** - only manual edits to generated files need tracking
148-
- **Try building early** - regenerate, build, and fix incrementally rather than trying to predict all issues upfront

0 commit comments

Comments
 (0)