Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to this project are documented in this file.

## [0.3.1] 2026-06-18

### Changed

- Update generated Mojo bindings, layout-test sidecars, and example smoke tests
for Mojo 1.0.0b2 syntax changes, including `def`, explicit `abi("C")`,
`reflect[T]`, and the new `UntrackedOrigin` / `UnsafeAnyOrigin` spelling
family.

## [0.3] 2026-06-01

### Added
Expand Down
64 changes: 32 additions & 32 deletions examples/cairo/cairo_smoke.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def _approx_eq(a: Float64, b: Float64, eps: Float64 = 1e-9) -> Bool:


def _draw_panel_border(
cr: Optional[UnsafePointer[cairo_t, MutExternalOrigin]],
cr: Optional[UnsafePointer[cairo_t, MutUntrackedOrigin]],
x: Float64,
y: Float64,
w: Float64,
Expand All @@ -49,7 +49,7 @@ def run_metadata_and_lifecycle_checks() raises:
_assert(
"version_string_nonnull",
cairo_version_string()
!= Optional[UnsafePointer[Int8, ImmutExternalOrigin]](),
!= Optional[UnsafePointer[Int8, ImmutUntrackedOrigin]](),
)

var surf = cairo_image_surface_create(
Expand All @@ -74,7 +74,7 @@ def run_metadata_and_lifecycle_checks() raises:
_assert(
"status_to_string_nonnull",
cairo_status_to_string(materialize[OK]())
!= Optional[UnsafePointer[Int8, ImmutExternalOrigin]](),
!= Optional[UnsafePointer[Int8, ImmutUntrackedOrigin]](),
)

cairo_save(cr)
Expand Down Expand Up @@ -118,12 +118,12 @@ def run_metadata_and_lifecycle_checks() raises:
_assert(
"get_target_nonnull",
cairo_get_target(cr)
!= Optional[UnsafePointer[cairo_surface_t, MutExternalOrigin]](),
!= Optional[UnsafePointer[cairo_surface_t, MutUntrackedOrigin]](),
)
_assert(
"get_group_target_nonnull",
cairo_get_group_target(cr)
!= Optional[UnsafePointer[cairo_surface_t, MutExternalOrigin]](),
!= Optional[UnsafePointer[cairo_surface_t, MutUntrackedOrigin]](),
)

cairo_destroy(cr)
Expand All @@ -132,7 +132,7 @@ def run_metadata_and_lifecycle_checks() raises:


def draw_composite_scene(
cr: Optional[UnsafePointer[cairo_t, MutExternalOrigin]]
cr: Optional[UnsafePointer[cairo_t, MutUntrackedOrigin]]
) raises:
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0)
cairo_paint(cr)
Expand Down Expand Up @@ -256,12 +256,12 @@ def draw_composite_scene(
cairo_pattern_get_matrix(rgba_pat, matrix)
cairo_pattern_set_matrix(
rgba_pat,
rebind[Optional[UnsafePointer[cairo_matrix_t, ImmutExternalOrigin]]](
rebind[Optional[UnsafePointer[cairo_matrix_t, ImmutUntrackedOrigin]]](
matrix
),
)
var surf_ptr = alloc[
Optional[UnsafePointer[cairo_surface_t, MutExternalOrigin]]
Optional[UnsafePointer[cairo_surface_t, MutUntrackedOrigin]]
](1)
_ok("pattern_get_surface", cairo_pattern_get_surface(surface_pat, surf_ptr))
var x0 = alloc[Float64](1)
Expand Down Expand Up @@ -353,7 +353,7 @@ def draw_composite_scene(
_assert(
"panel4_get_source_nonnull",
cairo_get_source(cr)
!= Optional[UnsafePointer[cairo_pattern_t, MutExternalOrigin]](),
!= Optional[UnsafePointer[cairo_pattern_t, MutUntrackedOrigin]](),
)
cairo_pattern_destroy(source_probe)
cairo_restore(cr)
Expand Down Expand Up @@ -386,7 +386,7 @@ def draw_composite_scene(
var family = CStringSlice("sans\0")
cairo_select_font_face(
cr,
rebind[UnsafePointer[Int8, ImmutExternalOrigin]](family.unsafe_ptr()),
rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](family.unsafe_ptr()),
materialize[CAIRO_FONT_SLANT_NORMAL](),
materialize[CAIRO_FONT_WEIGHT_BOLD](),
)
Expand All @@ -404,7 +404,7 @@ def draw_composite_scene(
cairo_font_face_destroy(ff2)

var tf = cairo_toy_font_face_create(
rebind[UnsafePointer[Int8, ImmutExternalOrigin]](family.unsafe_ptr()),
rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](family.unsafe_ptr()),
materialize[CAIRO_FONT_SLANT_ITALIC](),
materialize[CAIRO_FONT_WEIGHT_NORMAL](),
)
Expand All @@ -420,27 +420,27 @@ def draw_composite_scene(
_assert(
"panel6_toy_family_nonnull",
cairo_toy_font_face_get_family(tf)
!= Optional[UnsafePointer[Int8, ImmutExternalOrigin]](),
!= Optional[UnsafePointer[Int8, ImmutUntrackedOrigin]](),
)
cairo_font_face_destroy(tf)

var hello = CStringSlice("Hello Cairo\0")
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0)
cairo_move_to(cr, 12.0, 60.0)
cairo_show_text(
cr, rebind[UnsafePointer[Int8, ImmutExternalOrigin]](hello.unsafe_ptr())
cr, rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](hello.unsafe_ptr())
)
_ok("panel6_show_text", cairo_status(cr))
cairo_move_to(cr, 12.0, 120.0)
cairo_text_path(
cr, rebind[UnsafePointer[Int8, ImmutExternalOrigin]](hello.unsafe_ptr())
cr, rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](hello.unsafe_ptr())
)
_ok("panel6_text_path", cairo_status(cr))
cairo_new_path(cr)
var glyphs = cairo_glyph_allocate(4)
_assert(
"panel6_glyph_alloc_nonnull",
glyphs != Optional[UnsafePointer[cairo_glyph_t, MutExternalOrigin]](),
glyphs != Optional[UnsafePointer[cairo_glyph_t, MutUntrackedOrigin]](),
)
cairo_glyph_free(glyphs)
cairo_restore(cr)
Expand All @@ -450,7 +450,7 @@ def draw_composite_scene(
cairo_translate(cr, 20.0, 420.0)
var rec = cairo_recording_surface_create(
materialize[CAIRO_CONTENT_COLOR_ALPHA](),
Optional[UnsafePointer[cairo_rectangle_t, ImmutExternalOrigin]](),
Optional[UnsafePointer[cairo_rectangle_t, ImmutUntrackedOrigin]](),
)
_ok("panel7_recording_surface_create", cairo_surface_status(rec))
var rec_cr = cairo_create(rec)
Expand All @@ -472,20 +472,20 @@ def run_non_visual_object_checks() raises:
var opts = cairo_font_options_create()
_ok("font_options_create", cairo_font_options_status(opts))
var opts2 = cairo_font_options_copy(
rebind[UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]](opts)
rebind[UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]](opts)
)
_ok("font_options_copy", cairo_font_options_status(opts2))
cairo_font_options_merge(
opts,
rebind[UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]](opts2),
rebind[UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]](opts2),
)
_assert(
"font_options_equal",
cairo_font_options_equal(
rebind[UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]](
rebind[UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]](
opts
),
rebind[UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]](
rebind[UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]](
opts2
),
)
Expand All @@ -494,7 +494,7 @@ def run_non_visual_object_checks() raises:
_assert(
"font_options_hash_stable",
cairo_font_options_hash(
rebind[UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]](
rebind[UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]](
opts
)
)
Expand All @@ -506,7 +506,7 @@ def run_non_visual_object_checks() raises:
cairo_font_options_get_antialias(
rebind[
Optional[
UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]
UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]
]
](opts)
)
Expand All @@ -520,7 +520,7 @@ def run_non_visual_object_checks() raises:
cairo_font_options_get_subpixel_order(
rebind[
Optional[
UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]
UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]
]
](opts)
)
Expand All @@ -534,7 +534,7 @@ def run_non_visual_object_checks() raises:
cairo_font_options_get_hint_style(
rebind[
Optional[
UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]
UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]
]
](opts)
)
Expand All @@ -548,7 +548,7 @@ def run_non_visual_object_checks() raises:
cairo_font_options_get_hint_metrics(
rebind[
Optional[
UnsafePointer[cairo_font_options_t, ImmutExternalOrigin]
UnsafePointer[cairo_font_options_t, ImmutUntrackedOrigin]
]
](opts)
)
Expand All @@ -561,12 +561,12 @@ def run_non_visual_object_checks() raises:
rect_storage[0] = cairo_rectangle_int_t(10, 10, 60, 60)
var reg = cairo_region_create_rectangle(
rebind[
Optional[UnsafePointer[cairo_rectangle_int_t, ImmutExternalOrigin]]
Optional[UnsafePointer[cairo_rectangle_int_t, ImmutUntrackedOrigin]]
](rect_storage)
)
rect_storage.free()
var reg_const = rebind[
Optional[UnsafePointer[cairo_region_t, ImmutExternalOrigin]]
Optional[UnsafePointer[cairo_region_t, ImmutUntrackedOrigin]]
](reg)
_ok("region_create_rectangle", cairo_region_status(reg_const))
_assert(
Expand All @@ -591,7 +591,7 @@ def run_non_visual_object_checks() raises:
extents.free()
var reg2 = cairo_region_copy(reg_const)
var reg2_const = rebind[
Optional[UnsafePointer[cairo_region_t, ImmutExternalOrigin]]
Optional[UnsafePointer[cairo_region_t, ImmutUntrackedOrigin]]
](reg2)
_assert(
"region_equal_after_copy",
Expand All @@ -608,7 +608,7 @@ def run_non_visual_object_checks() raises:

var empty = cairo_region_create()
var empty_const = rebind[
Optional[UnsafePointer[cairo_region_t, ImmutExternalOrigin]]
Optional[UnsafePointer[cairo_region_t, ImmutUntrackedOrigin]]
](empty)
_ok("region_create_empty", cairo_region_status(empty_const))
_assert(
Expand All @@ -621,20 +621,20 @@ def run_non_visual_object_checks() raises:


def run_png_roundtrip_from_composite(
surface: Optional[UnsafePointer[cairo_surface_t, MutExternalOrigin]]
surface: Optional[UnsafePointer[cairo_surface_t, MutUntrackedOrigin]]
) raises:
var out_path = CStringSlice("/tmp/mojo_bindgen_cairo_smoke_composite.png\0")
_ok(
"surface_write_to_png",
cairo_surface_write_to_png(
surface,
rebind[UnsafePointer[Int8, ImmutExternalOrigin]](
rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](
out_path.unsafe_ptr()
),
),
)
var loaded = cairo_image_surface_create_from_png(
rebind[UnsafePointer[Int8, ImmutExternalOrigin]](out_path.unsafe_ptr())
rebind[UnsafePointer[Int8, ImmutUntrackedOrigin]](out_path.unsafe_ptr())
)
_ok("png_load", cairo_surface_status(loaded))
_assert("png_width", cairo_image_surface_get_width(loaded) == SCENE_W)
Expand Down
68 changes: 8 additions & 60 deletions examples/cairo/generate.sh
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,67 +1,15 @@
#!/usr/bin/env bash
# Example driver for the system Cairo header.
# It finds the real primary `cairo.h`, generates `cairo_bindings.mojo`, and
# builds/runs `cairo_smoke.mojo` to prove the emitted bindings link and work.
#
# Expects:
# - mojo-bindgen on PATH (e.g. `pixi shell` from the repository root), or Pixi
# at the repo root so this script can run `pixi run mojo-bindgen`.
# - Development headers for Cairo (e.g. libcairo2-dev on Debian/Ubuntu).
#
# Notes:
# - mojo-bindgen emits declarations from the primary header only, so this
# script locates `cairo/cairo.h` directly instead of using a wrapper.
# - The shared-library link name is `cairo`.
# Generate and run the Cairo owned-dl-handle example.
set -euo pipefail

HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$HERE/../.." && pwd)"
cd "$HERE"
source "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/common.sh"
example_init "${BASH_SOURCE[0]}"

source "$REPO_ROOT/examples/common.sh"
set_mojo_bindgen_cmd BG "$REPO_ROOT"
set_mojo_cmd MOJO "$REPO_ROOT"
HEADER="$(pkg_header cairo cairo/cairo.h)" || die "cairo/cairo.h not found; install Cairo development headers."
DYLIB="$(find_dylib cairo cairo)" || die "libcairo shared library not found."

find_cairo_h() {
local d
if command -v pkg-config >/dev/null 2>&1; then
while read -r -a flags; do
for flag in "${flags[@]}"; do
if [[ "$flag" == -I* ]]; then
d="${flag#-I}"
if [[ -f "$d/cairo/cairo.h" ]]; then
echo "$d/cairo/cairo.h"
return 0
fi
if [[ "$d" == */cairo && -f "$d/cairo.h" ]]; then
echo "$d/cairo.h"
return 0
fi
fi
done
done < <(pkg-config --cflags-only-I cairo 2>/dev/null || true)
fi
for d in /usr/include /usr/local/include /opt/homebrew/include; do
if [[ -f "$d/cairo/cairo.h" ]]; then
echo "$d/cairo/cairo.h"
return 0
fi
done
return 1
}
generate_owned_bindings "$HEADER" cairo cairo "$DYLIB" cairo_bindings.mojo
build_smoke cairo_smoke.mojo cairo_smoke

CAIRO_H="$(find_cairo_h)" || {
echo "mojo-bindgen cairo example: could not find cairo/cairo.h (install Cairo development headers)." >&2
exit 1
}

generate_bindings "$CAIRO_H" cairo cairo cairo_bindings.mojo

OBJ="$(mktemp "${TMPDIR:-/tmp}/cairo-bindings-XXXXXX.o")"
trap 'rm -f "$OBJ"' EXIT
build_bindings_object cairo_bindings.mojo "$OBJ"
"${MOJO[@]}" build cairo_smoke.mojo -I "$HERE" -Xlinker -lcairo -o cairo_smoke

echo "Wrote $HERE/cairo_bindings.mojo and cairo_bindings_layout_tests.mojo (from $CAIRO_H)"
echo "Running cairo_smoke (runtime render + file round-trip proof)"
echo "Wrote $HERE/cairo_bindings.mojo (dlopen: $DYLIB)"
"$HERE/cairo_smoke"
Loading
Loading