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
111 changes: 111 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

VILA (Vision Infrastructure Library Assembler) is a C++ infrastructure library for computer vision applications. It provides JSON-based configuration, logging with WPP support, reflection registry, error handling (Status/StatusOr), profiling tools, and a template DAG library.

## Build Systems

### Bazel (Primary)

```bash
# Build all tests
bazelisk test //tests/clim/... //tests/vila/...

# Build a specific test
bazelisk test //tests/clim:argparse_test

# Build with specific config (e.g., SYCL)
bazelisk build --config=sycl //...

# Run using legacy WORKSPACE (on Windows)
bazelisk --output_base="C:/temp/_vila_workspace" build --noenable_bzlmod //...
```

**Legacy WORKSPACE setup (Windows)** requires loading three workspace files in sequence:
```bazel
load("@vila//vila:workspace0.bzl", vila_workspace0 = "workspace")
vila_workspace0()
load("@vila//vila:workspace1.bzl", vila_workspace1 = "workspace")
vila_workspace1()
load("@vila//vila:workspace2.bzl", vila_workspace2 = "workspace")
```

### CMake

```bash
mkdir build && cmake -Bbuild -S. -GNinja
cmake --build build --config Release

# With testing enabled
cmake -Bbuild -S. -GNinja -DVILA_ENABLE_TESTING=ON
```

## Code Style

- **Style**: Based on Google C++ Style (see `.clang-format`)
- **Clang-tidy**: Configured in `.clang-tidy`, targets `clim/` and `vila/` headers only (excludes generated files)
- **Pre-commit hooks**: Run via `pre-commit run -s HEAD^ -o HEAD` (see `.pre-commit-config.yaml`)
- **Spell checking**: Codespell configured with words bag at `.github/WORDS_BAG.txt`

## Architecture

```
clim/ # Header-only utility library (math, strings, containers, etc.)
├── argparse/ # Command-line argument parsing
├── container/ # Bounding boxes, ring buffers, etc.
├── filter/ # Kalman and alpha-beta filters
├── hash/ # CityHash, MurmurHash
├── math/ # Quaternion, numerical utilities
├── os/ # OS utilities (aligned malloc, barriers)
├── path/ # Cross-platform path handling
├── reflection/ # Reflection registry
├── string/ # String splitting, stripping, const_string
├── vt/ # Vector math (GEMM, neural network ops)
└── zip/ # Zip utility functions

vila/ # Core library components
├── config/ # JSON-based configuration system
├── graph/ # Template header-only DAG (dag.h, graph.h, route.h, traversal.h)
├── hook/ # Windows DLL hooking (detours)
├── logging/ # Logger with WPP support (code_location, logger)
├── profiling/ # ITT, timer, trace utilities
├── status/ # Status and StatusOr error handling
├── widget/ # (UI components)
└── bazel/ # Bazel-specific build rules and toolchains

python/ # Python bindings via nanobind/pybind11
tests/ # GoogleTest-based C++ tests
```

## Key Dependencies (via Bazel)

- `fmt` (12.1.0) - Formatting library
- `spdlog` - Logging library
- `googletest` - Testing framework
- `google_benchmark` - Benchmarking
- `rules_foreign_cc` - CMake/ ninja build support

## Testing

```bash
# C++ tests (Bazel)
bazelisk test //tests/clim/... //tests/vila/...

# Python tests
pip install -e python[test]
pytest --cov=python/vila python/tests
```

## Windows-Specific Notes

- Default C++ standard: C++17
- Windows WPP logging disabled by default (see commit ed44f79)
- Windows-specific configs use `select()` with `//conditions:default` since some build configs are Windows-only
- The `range_test` is Windows-only and requires C++20

## Editor Setup

The project includes `.vscode/` settings for convenience with bazelized projects.
3 changes: 3 additions & 0 deletions .github/workflows/build-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Setup system python env
run: |
python -m pip install -r tests/vila/requirements_tvm_ffi_test.txt
- uses: bazel-contrib/setup-bazel@0.15.0
with:
bazelisk-cache: true
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ dist/
/external
/bazel-*
htmlcov/

# AI
.claude/settings.local.json
32 changes: 9 additions & 23 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ repos:
- id: check-added-large-files
args: ["--maxkb=1024"]
- id: requirements-txt-fixer
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.8
hooks:
# Run the linter.
- id: ruff-check
args: [--fix]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
hooks:
Expand All @@ -22,26 +31,3 @@ repos:
rev: 1.4.3
hooks:
- id: cmakelint
- repo: https://github.com/PyCQA/isort
rev: 8.0.1
hooks:
- id: isort
args:
- '--profile=black'
- repo: https://github.com/psf/black
rev: 26.3.0
hooks:
- id: black
args:
- '-vv'
- repo: https://github.com/PyCQA/isort
rev: 8.0.1
hooks:
- id: isort
args:
- '--profile=black'
- repo: https://github.com/pycqa/flake8
rev: 7.3.0
hooks:
- id: flake8
additional_dependencies: [Flake8-pyproject]
12 changes: 12 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.defaults(python_version = "3.12")
python.toolchain(python_version = "3.12")

pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
hub_name = "vila_pip_deps",
python_version = "3.12",
requirements_lock = "//tests/vila:requirements_tvm_ffi_test.txt",
)
use_repo(pip, "vila_pip_deps")

wdk_config_ext = use_extension("@vila//vila/bazel/bzlmod:extensions.bzl", "wdk_configure_extension")
use_repo(wdk_config_ext, "local_config_wdk")

Expand All @@ -53,6 +61,10 @@ use_repo(hedron_ext, "hedron_compile_commands")
sycl_config_ext = use_extension("@vila//vila/bazel/bzlmod:extensions.bzl", "sycl_configure_extension")
use_repo(sycl_config_ext, "local_config_sycl")

# TVM FFI support (optional - requires: pip install apache-tvm-ffi)
tvm_ffi_ext = use_extension("@vila//vila/bazel/bzlmod:extensions.bzl", "tvm_ffi_extension")
use_repo(tvm_ffi_ext, "tvm_ffi")

register_toolchains(
# to use sycl specify: --config=sycl
"@local_config_sycl//:cc-toolchain-x64_sycl",
Expand Down
17 changes: 16 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ vila_workspace1()

load("@vila//vila:workspace2.bzl", vila_workspace2 = "workspace")

vila_workspace2(sycl = True)
vila_workspace2(
sycl = False,
tvm_ffi = True,
)
Comment on lines +29 to +32

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WORKSPACE previously enabled SYCL via sycl = True, but this change forces sycl = False while adding tvm_ffi = True. This looks unrelated to the PR’s stated goal (adding tvm-ffi) and will change developer builds unexpectedly. Consider preserving the prior sycl = True setting (or omit the argument to keep the existing behavior) and only add tvm_ffi = True.

Copilot uses AI. Check for mistakes.

# load("@bazel_features//:deps.bzl", "bazel_features_deps")
# load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
Expand All @@ -47,3 +50,15 @@ python_register_toolchains(
name = "local_config_python",
python_version = "3.13",
)

load("@rules_python//python:pip.bzl", "pip_parse")

pip_parse(
name = "vila_pip_deps",
python_interpreter = "python",
requirements_lock = "//tests/vila:requirements_tvm_ffi_test.txt",
)

load("@vila_pip_deps//:requirements.bzl", "install_deps")

install_deps()
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@ disable = [
"R",
"I",
]

[tool.ruff]
line-length = 88

[tool.ruff.lint]
select = ["E", "F", "UP", "I"]
ignore = ["E203", "E231", "E241"]
24 changes: 24 additions & 0 deletions tests/vila/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
"""

load("@rules_cc//cc:defs.bzl", "cc_binary")
load("@rules_python//python:defs.bzl", "py_test")
load("@vila_pip_deps//:requirements.bzl", "requirement")
load("//vila/bazel/vila:vila.bzl", "vila_cc_test")

cc_binary(
name = "tvm_ffi_call",
srcs = ["tvm_ffi_call.cpp"],
linkshared = True,
deps = [
"@fmt",
"@tvm_ffi",
],
)

py_test(
name = "tvm_ffi_call_test",
srcs = ["tvm_ffi_call_test.py"],
data = [":tvm_ffi_call"],
deps = [
requirement("apache-tvm-ffi"),
requirement("numpy"),
requirement("typing-extensions"),
],
)

vila_cc_test(
name = "config_test",
srcs = ["config_test.cpp"],
Expand Down
3 changes: 3 additions & 0 deletions tests/vila/requirements_tvm_ffi_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
apache-tvm-ffi==0.1.9
numpy==2.2.6
typing-extensions==4.15.0
104 changes: 104 additions & 0 deletions tests/vila/tvm_ffi_call.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright (C) 2026 The VILA Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// This file demonstrates how to use TVM FFI to export C++ functions
// that can be called from Python via tvm_ffi.load_module().
//
// TVM FFI provides a simple mechanism to create shared libraries (.dll on Windows,
// .so on Linux) that can be loaded dynamically from Python. Functions exported
// using TVM_FFI_DLL_EXPORT_TYPED_FUNC are automatically discoverable.
//
// Key concepts:
// 1. TVM_FFI_DLL_EXPORT_TYPED_FUNC(ExportName, FunctionPtr)
// - ExportName: the name exposed to Python (e.g., "add_one_tensor")
// - FunctionPtr: a C++ function pointer with matching signature
// 2. The C++ function takes a tvm::ffi::Tensor and returns a tvm::ffi::Tensor
// 3. TVM FFI automatically converts numpy arrays to Tensor via DLPack
//
// Example usage in Python:
// import tvm_ffi
// import numpy as np
// mod = tvm_ffi.load_module("path/to/tvm_ffi_call.dll")
// func = mod.add_one_tensor
// x = np.array([1.0, 2.0, 3.0], dtype=np.float32)
// result = func(x) # Returns array([2.0, 3.0, 4.0], dtype=np.float32)

#include <tvm/ffi/tvm_ffi.h>

#include <cstring>
#include <cstdint>

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

malloc/free are used but <cstdlib> isn’t included. Some toolchains will fail to compile this (especially with strict warning settings). Please include <cstdlib> (or use std::malloc/std::free accordingly).

Suggested change
#include <cstdint>
#include <cstdint>
#include <cstdlib>

Copilot uses AI. Check for mistakes.

// CPU allocator for creating output tensors
struct CPUAlloc {
void AllocData(DLTensor* tensor) {
size_t size = tvm::ffi::GetDataSize(*tensor);
tensor->data = malloc(size);
}

void FreeData(DLTensor* tensor) {
if (tensor->data != nullptr) {
free(tensor->data);
tensor->data = nullptr;
}
}
};

// AddOneTensor_ takes an input tensor and returns a new tensor with each
// element incremented by 1. This demonstrates:
// 1. Receiving a Tensor from Python (via DLPack conversion)
// 2. Creating a new output tensor using TVM FFI's tensor API
// 3. Performing element-wise operations on tensor data
//
// @param input The input tensor (float32)
// @return A new tensor with each element = input element + 1
tvm::ffi::Tensor AddOneTensor_(const tvm::ffi::Tensor& input) {
// Get a view of the input tensor for reading
tvm::ffi::TensorView view(input);

// Verify the input is float32 for this simple example
if (view.dtype().code != kDLFloat || view.dtype().bits != 32 || view.dtype().lanes != 1) {
TVM_FFI_THROW(ValueError) << "Expected float32 tensor, got dtype with code="
<< static_cast<int>(view.dtype().code)
<< ", bits=" << static_cast<int>(view.dtype().bits);
}

// Create output tensor with the same shape
tvm::ffi::Tensor output = tvm::ffi::Tensor::FromNDAlloc(
CPUAlloc(), // allocator
view.shape(), // shape
view.dtype(), // dtype (float32)
input.device() // device (cpu)
);

// Copy data and add 1 to each element
const float* in_data = static_cast<const float*>(view.data_ptr());

Check warning on line 87 in tests/vila/tvm_ffi_call.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the redundant type with "auto".

See more on https://sonarcloud.io/project/issues?id=llteco_vila&issues=AZ1T7Dbid1Sm4qOx1umN&open=AZ1T7Dbid1Sm4qOx1umN&pullRequest=12
float* out_data = static_cast<float*>(output.data_ptr());

Check warning on line 88 in tests/vila/tvm_ffi_call.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the redundant type with "auto".

See more on https://sonarcloud.io/project/issues?id=llteco_vila&issues=AZ1T7Dbid1Sm4qOx1umO&open=AZ1T7Dbid1Sm4qOx1umO&pullRequest=12

int64_t numel = view.numel();
for (int64_t i = 0; i < numel; ++i) {
out_data[i] = in_data[i] + 1.0f;
}

return output;
}

// TVM_FFI_DLL_EXPORT_TYPED_FUNC registers the C++ function AddOneTensor_ as "add_one_tensor"
// in the shared library's exports. When Python loads this library via tvm_ffi,
// it can access the function as mod.add_one_tensor.
//
// The macro handles all the boilerplate for exporting a typed function to Python,
// including function signature registration and ABI compatibility.
TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_tensor, AddOneTensor_)
Loading
Loading