chore(cpp): set up standalone CLion project for parallel C++ sessions

cpp/ now has its own CMakeLists.txt that independently fetches mlx-c
v0.4.1, allowing a CLion Claude to build and explore the C API surface
without conflicting with the Go-side CMake build. Updated CLAUDE.md to
reflect cpp/ as the project root with standalone build instructions.

Added priority tasks to cpp/TODO.md: mlx_contiguous search, eval
semantics verification, mlx_cumsum check for TopP sampling.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Snider 2026-02-19 18:49:16 +00:00
parent 28b5c5bb47
commit 3b155f6ca7
3 changed files with 54 additions and 40 deletions

View file

@ -14,28 +14,40 @@ You are the C++ specialist for `forge.lthn.ai/core/go-mlx`. This Go package wrap
## Project Layout
This directory (`cpp/`) is your CLion project root. It has its own CMakeLists.txt that fetches mlx-c v0.4.1 independently.
```
go-mlx/ ← CMakeLists.txt lives here (CLion project root)
├── CMakeLists.txt ← Fetches mlx-c v0.4.1, builds to dist/
├── cpp/ ← YOUR workspace docs (this directory)
│ ├── CLAUDE.md ← This file
│ ├── TODO.md ← C++ task queue
│ └── FINDINGS.md ← C++ research notes
├── build/ ← CMake build directory (gitignored)
│ └── _deps/
│ ├── mlx-c-src/ ← mlx-c v0.4.1 source (24 .cpp, 27 .h)
│ │ └── mlx/c/ ← The C API headers + implementations
│ └── mlx-src/ ← MLX C++ framework source (Metal shaders, ops)
├── dist/ ← Installed artifacts (gitignored)
│ ├── include/mlx/c/ ← Headers used by Go CGO
│ └── lib/ ← libmlxc.dylib, libmlx.dylib
└── *.go ← Go bindings (GoLand Claude's domain)
cpp/ ← CLion project root (this directory)
├── CLAUDE.md ← This file
├── TODO.md ← C++ task queue
├── FINDINGS.md ← C++ research notes
├── CMakeLists.txt ← Standalone CMake, fetches mlx-c v0.4.1
└── build/ ← CMake build dir (after first build)
└── _deps/
├── mlx-c-src/ ← mlx-c v0.4.1 source (24 .cpp, 27 .h)
│ └── mlx/c/ ← The C API headers + implementations
└── mlx-src/ ← MLX C++ framework source
../ ← Parent: go-mlx (GoLand Claude's domain)
├── CMakeLists.txt ← Go side's CMake (same mlx-c version)
├── *.go ← Go bindings
├── dist/ ← Go side's installed libs
└── build/ ← Go side's CMake build
```
## Key Files
## Build
```bash
# From cpp/ directory:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
# Source lands in: build/_deps/mlx-c-src/mlx/c/
```
After first build, all mlx-c headers and source are available for reading and indexing.
## Key Files (after build)
### mlx-c Headers (the API surface Go binds to)
- `build/_deps/mlx-c-src/mlx/c/array.h` — Array creation, data access, shape
@ -50,27 +62,9 @@ go-mlx/ ← CMakeLists.txt lives here (CLion project ro
- `build/_deps/mlx-c-src/mlx/c/memory.h` — Memory management
### CMake
- `go-mlx/CMakeLists.txt` — Top-level, fetches mlx-c v0.4.1 from GitHub
- `cpp/CMakeLists.txt` — This project's build config (standalone)
- `build/_deps/mlx-c-src/CMakeLists.txt` — mlx-c's own build config
## Build
```bash
# From go-mlx root:
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=dist -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
cmake --install build
# Or via Go:
go generate ./...
```
### CMake Settings
- `MLX_BUILD_SAFETENSORS=ON`
- `MLX_BUILD_GGUF=OFF`
- `BUILD_SHARED_LIBS=ON`
- macOS deployment target: 26.0
## How Go Binds to mlx-c
Go files use CGO with `#include "mlx/c/mlx.h"` and link via:
@ -87,8 +81,8 @@ Each Go function calls the corresponding `mlx_*` C function. The pattern is:
## Communication Protocol
- **Receiving work**: Tasks appear in `cpp/TODO.md`, written by the GoLand Claude or Virgil
- **Reporting findings**: Write to `cpp/FINDINGS.md`
- **Receiving work**: Tasks appear in `TODO.md`, written by the GoLand Claude or Virgil
- **Reporting findings**: Write to `FINDINGS.md`
- **Requesting Go changes**: Describe what the GoLand Claude needs to change in FINDINGS.md
- **Completing tasks**: Mark `[x]` in TODO.md with notes

18
cpp/CMakeLists.txt Normal file
View file

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.24)
project(go-mlx-cpp LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
# Fetch mlx-c v0.4.1 — same version as the Go side
include(FetchContent)
FetchContent_Declare(
mlx-c
GIT_REPOSITORY https://github.com/ml-explore/mlx-c.git
GIT_TAG v0.4.1
)
set(MLX_BUILD_SAFETENSORS ON CACHE BOOL "" FORCE)
set(MLX_BUILD_GGUF OFF CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(mlx-c)

View file

@ -14,6 +14,8 @@ Tasks for the CLion Claude session. Written by GoLand Claude or Virgil.
- [ ] **Find `mlx_contiguous` or equivalent**`Floats()`/`DataInt32()` on non-contiguous arrays (transpose, broadcast, slice views) returns wrong data because `mlx_array_data_float32` returns the physical buffer, not the logical layout. Need a C function that copies a non-contiguous array to contiguous memory. Check if `mlx_contiguous` exists in mlx-c headers or if we need `mlx_reshape` to force a copy. This is a data correctness bug — see FINDINGS.md in project root.
- [ ] **Verify `mlx_array_data_*` eval semantics** — Does `mlx_array_data_float32()` trigger evaluation (like C++ `array::data()` does), or must we call `mlx_eval` first? The Go side calls `Materialize()` before data access but some code paths might skip it.
- [ ] **Check if `mlx_cumsum` exists** — The Go TopP (nucleus) sampler in `sample/sample.go` is a stub because it needs cumulative sum along an axis. Check if `mlx_cumsum` or equivalent is in `ops.h`. If so, the GoLand Claude can implement proper TopP sampling.
- [ ] **Survey `mlx_contiguous` / `mlx_flatten` / `mlx_copy`** — We need a way to force an array into contiguous row-major memory. Check all of: `mlx_contiguous`, `mlx_flatten`, `mlx_copy`, `mlx_as_contiguous`. Any of these would fix the Floats() bug.
## Standing Tasks