This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git
The following commit(s) were added to refs/heads/main by this push:
new 9582540 chore: Add linters for `.rst`, `.md` and `.yaml` (#46)
9582540 is described below
commit 95825407609f1da8e59bdcafb1d0a6d0b09c14c1
Author: Junru Shao <[email protected]>
AuthorDate: Tue Sep 23 06:55:47 2025 -0700
chore: Add linters for `.rst`, `.md` and `.yaml` (#46)
This PR integers new linters for
- YAML
- Markdown, and
- reStructuredText
files into the pre-commit workflow, ensures that docs and configs adhere
to defined style guides, improving overall readability and
maintainability.
The changes also include initial cleanup of existing documentation to
align with these new standards.
---
.asf.yaml | 6 ++---
.clang-format | 2 +-
.github/workflows/ci_test.yml | 2 +-
.markdownlint-cli2.yaml | 19 ++++++++++++++
.pre-commit-config.yaml | 20 +++++++++++++++
.yamllint.yaml | 32 +++++++++++++++++++++++
docs/.rstcheck.cfg | 4 +++
docs/concepts/abi_overview.md | 20 +++++++++------
docs/get_started/install.md | 10 +++-----
docs/get_started/quick_start.md | 16 +++++++-----
docs/guides/compiler_integration.md | 51 ++++++++++++++++++++-----------------
docs/guides/cpp_guide.md | 17 ++++++-------
docs/guides/packaging.md | 11 +++++---
docs/guides/python_guide.md | 6 ++++-
examples/packaging/README.md | 6 +++--
tests/lint/check_file_type.py | 1 +
16 files changed, 159 insertions(+), 64 deletions(-)
diff --git a/.asf.yaml b/.asf.yaml
index 1163ad3..4c917af 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -36,17 +36,17 @@ github:
enabled_merge_buttons:
# enable squash button:
- squash: true
+ squash: true
# default commit message when merging with a squash commit
# can either be: DEFAULT | PR_TITLE | PR_TITLE_AND_COMMIT_DETAILS |
PR_TITLE_AND_DESC
squash_commit_message: PR_TITLE_AND_DESC
# enable merge button:
- merge: false
+ merge: false
# default commit message when merging with a merge commit
# can either be: DEFAULT | PR_TITLE | PR_TITLE_AND_DESC
merge_commit_message: DEFAULT
# disable rebase button:
- rebase: false
+ rebase: false
notifications:
commits: [email protected]
diff --git a/.clang-format b/.clang-format
index 9d622b9..b61ed53 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,5 +4,5 @@
# https://clang.llvm.org/docs/ClangFormat.html
BasedOnStyle: Google
DerivePointerAlignment: false
-ColumnLimit: 100
+ColumnLimit: 100
PointerAlignment: Left
diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml
index eee0c55..2edd8c2 100644
--- a/.github/workflows/ci_test.yml
+++ b/.github/workflows/ci_test.yml
@@ -50,7 +50,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd #
v3.0.1
+ - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd #
v3.0.1
doc:
needs: [lint, prepare]
diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml
new file mode 100644
index 0000000..8d56f07
--- /dev/null
+++ b/.markdownlint-cli2.yaml
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+config:
+ MD013: false
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 329c00c..41cabcc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -53,6 +53,13 @@ repos:
- id: trailing-whitespace
- id: check-yaml
- id: check-toml
+ - repo: https://github.com/adrienverge/yamllint
+ rev: v1.35.1
+ hooks:
+ - id: yamllint
+ args:
+ - --config-file
+ - .yamllint.yaml
- repo: https://github.com/ComPWA/taplo-pre-commit
rev: v0.9.3
hooks:
@@ -83,6 +90,19 @@ repos:
rev: v0.10.0.1
hooks:
- id: shellcheck
+ - repo: https://github.com/DavidAnson/markdownlint-cli2
+ rev: v0.14.0
+ hooks:
+ - id: markdownlint-cli2
+ - repo: https://github.com/rstcheck/rstcheck
+ rev: v6.2.4
+ hooks:
+ - id: rstcheck
+ additional_dependencies:
+ - rstcheck[sphinx]
+ args:
+ - --config
+ - docs/.rstcheck.cfg
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.17.0"
hooks:
diff --git a/.yamllint.yaml b/.yamllint.yaml
new file mode 100644
index 0000000..417d517
--- /dev/null
+++ b/.yamllint.yaml
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+extends: default
+
+rules:
+ document-start: disable
+ line-length:
+ max: 120
+ level: warning
+ truthy:
+ allowed-values:
+ - "on"
+ - "off"
+ - "yes"
+ - "no"
+ - "true"
+ - "false"
diff --git a/docs/.rstcheck.cfg b/docs/.rstcheck.cfg
new file mode 100644
index 0000000..0ed2999
--- /dev/null
+++ b/docs/.rstcheck.cfg
@@ -0,0 +1,4 @@
+[rstcheck]
+report_level = warning
+ignore_directives = automodule, autosummary, currentmodule, toctree, ifconfig
+ignore_roles = ref, cpp:class, cpp:func, py:func
diff --git a/docs/concepts/abi_overview.md b/docs/concepts/abi_overview.md
index 0843efd..d134e6b 100644
--- a/docs/concepts/abi_overview.md
+++ b/docs/concepts/abi_overview.md
@@ -95,6 +95,7 @@ int CallTVMFFISafeCall(const char* param0, int param1) {
```
At a high level, the `TVMFFISafeCallType` signature does the following things:
+
- Arguments and return values are stored in structured `TVMFFIAny`
- Each value comes with a `type_index` to indicate its type
- Values are stored in union fields, depending on the specific type.
@@ -110,7 +111,6 @@ treatment of each of these specific topics.
You can keep this example in mind as the overall picture and refine it as you
read through
the following sections.
-
## TVMFFIAny Storage Format
To start with, we need a mechanism to store the values that are passed across
machine learning frameworks.
@@ -146,7 +146,6 @@ TVMFFIAny is a 16-byte C structure that follows the design
principle of tagged-u
- `v_obj` can also point to a managed heap-allocated object, which we will
discuss next.
- The second field stores metadata for small strings.
-
### Storing a POD Value
There are many values that are plain-old-data types. In such cases, we store
them directly
@@ -185,7 +184,6 @@ and hash TVMFFIAny in bytes for quick equality checks
without going through
type index switching.
:::
-
## Object Storage Format
When TVMFFIAny points to a heap-allocated object (such as n-dimensional
arrays),
@@ -214,6 +212,7 @@ typedef struct TVMFFIObject {
- When `weak_ref_count` gets to zero, the deleter needs to free the memory
allocated by self.
**Rationales:** There are several considerations when designing the data
structure:
+
- `type_index` enables runtime dynamic type checking and casting.
- We introduce weak/strong ref counters so we can be compatible with systems
that need weak pointers.
- The weak ref counter is kept as 32-bit so we can pack the object header as
24 bytes.
@@ -223,7 +222,6 @@ The object format provides a unified way to manage object
life-cycle and dynamic
for heap-allocated objects, including Shape, Tensor,
Function, Array, Map and other custom objects.
-
### DLPack Compatible Tensor
We provide first-class support for DLPack raw unmanaged pointer support as
well as a managed Tensor object that
@@ -244,9 +242,10 @@ DLTensor* ReadDLTensorPtr(const TVMFFIAny *value) {
}
assert(value->type_index == kTVMFFITensor);
return reinterpret_cast<DLTensor*>(
- reinterpret_cast<char*>(value->v_obj) + sizeof(TVMFFIObject));
+ reinterpret_cast<char*>(value->v_obj) + sizeof(TVMFFIObject));
}
```
+
The above code can be used as a reference to implement compiler codegen for
data.
Note that the C++ API automatically handles such conversion.
@@ -264,7 +263,8 @@ values are unique by appending namespace prefix to the key.
An `TVMFFIAny` can either be treated as a strongly managed value
(corresponding to `ffi::Any` in C++),
or an unmanaged value (corresponding to `ffi::AnyView` in C++).
-- For POD types, there is no difference between the two
+
+- For POD types, there is no difference between the two.
- For object types, copying of AnyView should not change reference counters,
while copying and deletion
of managed Any should result in increase and decrease of strong reference
counters.
- When we convert AnyView to Any, we will convert raw C string `const char*`
and `const TVMFFIByteArray*`
@@ -317,6 +317,7 @@ to an on-heap object.
```
We call this approach a packed function, as it provides a single signature to
represent all functions in a "type-erased" way. It saves the need to declare
and jit shim for each FFI function call while maintaining reasonable
efficiency. This mechanism enables the following scenarios:
+
- Calling from Dynamic Languages (e.g., Python): we provide a tvm_ffi binding
that prepares the args based on dynamically examining Python arguments passed
in.
- Calling from Static Languages (e.g., C++): For static languages, we can
leverage C++ templates to directly instantiate the arguments on the stack,
saving the need for dynamic examination.
- Dynamic language Callbacks: the signature enables us to easily bring dynamic
language (Python) callbacks as ffi::Function, as we can take each argument and
convert to the dynamic values.
@@ -324,7 +325,6 @@ We call this approach a packed function, as it provides a
single signature to re
We support first-class Function objects that allow us to also pass
function/closures from different places around, enabling cool usages such as
quick python callback for prototyping, and dynamic Functor creation for
driver-based kernel launching.
-
## Error Handling
Most TVM FFI C API calls, including `TVMFFISafeCallType` uses the return value
to
@@ -347,6 +347,7 @@ The caller can retrieve the error from thread-local error
storage
using `TVMFFIErrorMoveFromRaised` function.
The ABI stores Error also as a specific Object,
the overall error object is stored as follows
+
```c++
/*!
* \brief Error cell used in error object following header.
@@ -385,7 +386,8 @@ class ErrorObj : public ffi::Object, public TVMFFIErrorCell
{
The error object stores kind, message and backtrace as string. When possible,
we store the backtrace in the same format of python-style (see an example as
follows):
-```
+
+```text
File "src/extension.cc", line 45, in void
my_ffi_extension::RaiseError(tvm::ffi::String)
```
@@ -407,6 +409,7 @@ its `type_index`.
- `kTVMFFIStr`: on-heap string object for strings that are longer than 7
characters.
The following code shows the layout of the on-heap string object.
+
```c++
// span-like data structure to store header and length
typedef struct {
@@ -420,6 +423,7 @@ class StringObj : public ffi::Object, public
TVMFFIByteArray {
```
The following code shows how to read a string from `TVMFFIAny`
+
```c++
TVMFFIByteArray ReadString(const TVMFFIAny *value) {
TVMFFIByteArray ret;
diff --git a/docs/get_started/install.md b/docs/get_started/install.md
index 622f95c..5e97143 100644
--- a/docs/get_started/install.md
+++ b/docs/get_started/install.md
@@ -38,7 +38,6 @@ tvm-ffi-config -h
This configuration tool is also useful in various ways to help you build
libraries with tvm-ffi.
-
## Install From Source
You can also build and install tvm-ffi from source.
@@ -48,13 +47,12 @@ You can also build and install tvm-ffi from source.
- CMake (>= 3.24.0)
- Git
- A recent C++ compiler supporting C++17, at minimum:
- - GCC 7.1
- - Clang 5.0
- - Apple Clang 9.3
- - Visual Studio 2019 (v16.7)
+ - GCC 7.1
+ - Clang 5.0
+ - Apple Clang 9.3
+ - Visual Studio 2019 (v16.7)
- Python (>= 3.9)
-
Developers can clone the source repository from GitHub.
```bash
diff --git a/docs/get_started/quick_start.md b/docs/get_started/quick_start.md
index b422d10..9a4ae3d 100644
--- a/docs/get_started/quick_start.md
+++ b/docs/get_started/quick_start.md
@@ -27,7 +27,6 @@ Let us first get started by build and run the example. The
example will show us:
- How to load and run tvm-ffi based library from python
- How to load and run tvm-ffi based library from c++
-
Before starting, ensure you have:
- TVM FFI installed following [installation](./install.md)
@@ -46,6 +45,7 @@ cd tvm-ffi
The examples are now in the example folder, you can quickly build
the example using the following command.
+
```bash
cd examples/quick_start
@@ -55,19 +55,20 @@ cmake --build build --parallel
```
After the build finishes, you can run the python examples by
-```
+
+```bash
python run_example.py
```
You can also run the c++ example
-```
+```bash
./build/run_example
```
If the CUDA toolkit is available, the GPU demo binary is built alongside the
CPU sample:
-```
+```bash
./build/run_example_cuda
```
@@ -77,7 +78,7 @@ Now we have quickly try things out. Let us now walk through
the details of the e
Specifically, in this example, we create a simple "add one" operation that
adds 1 to each element of an input
tensor and expose that function as TVM FFI compatible function. The key file
structures are as follows:
-```
+```text
examples/quick_start/
├── src/
│ ├── add_one_cpu.cc # CPU implementation
@@ -123,6 +124,7 @@ TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cpu,
tvm_ffi_example::AddOne);
```
**Key Points:**
+
- Functions take `tvm::ffi::Tensor` parameters for cross-language compatibility
- The `TVM_FFI_DLL_EXPORT_TYPED_FUNC` macro exposes the function with a given
name
@@ -150,11 +152,11 @@ TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cuda,
tvm_ffi_example::AddOneCUDA);
```
**Key Points:**
+
- We use `TVMFFIEnvGetStream` to obtain the current stream from the
environement
- When invoking ffi Function from python end with PyTorch tensor as argument,
the stream will be populated with torch's current stream.
-
### Working with PyTorch
Atfer build, we will create library such as `build/add_one_cuda.so`, that can
be loaded by
@@ -265,6 +267,7 @@ int __tvm_ffi_add_one_c(
return 0; // Success
}
```
+
To compile this code, you need to add
{py:func}`tvm_ffi.libinfo.find_include_paths` to your include
path and link the shared library that can be found through
{py:func}`tvm_ffi.libinfo.find_libtvm_ffi`.
We also provide command line tools to link, so you can compile with the
following command:
@@ -276,6 +279,7 @@ gcc -shared -fPIC `tvm-ffi-config --cflags` \
```
The main takeaway points are:
+
- Function symbols follow name `int __tvm_ffi_<name>`
- The function follows signaure of `TVMFFISafeCallType`
- Use `TVMFFIAny` to handle dynamic argument types
diff --git a/docs/guides/compiler_integration.md
b/docs/guides/compiler_integration.md
index 7338dbf..1c8fa58 100644
--- a/docs/guides/compiler_integration.md
+++ b/docs/guides/compiler_integration.md
@@ -83,21 +83,23 @@ int __tvm_ffi_add_one_c(
```
Some of the key takeaways include:
+
- Prefix the symbol with `__tvm_ffi_`
- Call {cpp:func}`TVMFFIEnvGetStream` to get the current environment stream
- Use return value for error handling, set error via
{cpp:func}`TVMFFIErrorSetRaisedFromCStr`.
You can also check out the [ABI overview](../concepts/abi_overview.md) for a
more complete guide.
-
## Graph Compilers
Machine learning graph compilers take computational graphs and can integrate
with TVM FFI through:
- Supporting the `call_tvm_ffi` primitive that calls into `my_func` that
follows the ABI:
-```python
-Op.call_tvm_ffi("my_func", *args)
-```
+
+ ```python
+ Op.call_tvm_ffi("my_func", *args)
+ ```
+
- Using the module API to load the modules into context and run.
Alternatively, look up
global functions that are registered and invoke them.
- For ahead-of-time compilation (AOT) with minimum runtime, the AOT compiler
can generate
@@ -109,7 +111,6 @@ This approach provides a unified mechanism to call into any
libraries and other
that expose kernels following the FFI convention, enabling seamless
interoperability
with various kernel DSLs and libraries.
-
## Runtime and State Management for Compilers
While TVM FFI provides a standard ABI for compiler-generated kernels, many
compilers and domain-specific languages
@@ -124,25 +125,27 @@ This library exposes its functionality by registering
functions as global `tvm::
Here's a breakdown of the process:
-1. **Define a Global State**: Create a class or structure to hold your
compiler's runtime state. A simple singleton pattern is often used for this.
-2. **Register Global Functions**: Use the `TVM_FFI_STATIC_INIT_BLOCK()` macro
to register a global function that returns a pointer to your state. For example:
- ```c++
- class GlobalState {
- ... // your state variables here
- public:
- GlobalState* Global() {
- static auto *inst = new GlobalState();
- return inst;
- }
- };
- TVM_FFI_STATIC_INIT_BLOCK() {
- using refl = tvm::ffi::reflection;
- refl.GlobalDef().def("mylang.get_global_state", []()-> void*{ return
GlobalState::Global()});
- // other runtime APIs can be registered here
- }
- ```
- This method allows both C++ and Python to access the runtime state through
a consistent API.
-3. **Access State from Kernels**: Within your compiler-generated kernels, you
can use
+1. **Define a Global State**: Create a class or structure to hold your
compiler's runtime state. A simple singleton pattern is often used for this.
+2. **Register Global Functions**: Use the `TVM_FFI_STATIC_INIT_BLOCK()` macro
to register a global function that returns a pointer to your state. For example:
+
+ ```c++
+ class GlobalState {
+ ... // your state variables here
+ public:
+ GlobalState* Global() {
+ static auto *inst = new GlobalState();
+ return inst;
+ }
+ };
+ TVM_FFI_STATIC_INIT_BLOCK() {
+ using refl = tvm::ffi::reflection;
+ refl.GlobalDef().def("mylang.get_global_state", []()-> void*{ return
GlobalState::Global()});
+ // other runtime APIs can be registered here
+ }
+ ```
+
+ This method allows both C++ and Python to access the runtime state through
a consistent API.
+3. **Access State from Kernels**: Within your compiler-generated kernels, you
can use
`GetGlobalRequired("mylang.get_global_state")` in C++ or the C equivalent
`TVMFFIGetGlobalFunction("mylang.get_global_state", ...)` to get the
function and then call it to retrieve the state
pointer.
diff --git a/docs/guides/cpp_guide.md b/docs/guides/cpp_guide.md
index 836cb84..e37058b 100644
--- a/docs/guides/cpp_guide.md
+++ b/docs/guides/cpp_guide.md
@@ -14,10 +14,10 @@
<!--- KIND, either express or implied. See the License for the -->
<!--- specific language governing permissions and limitations -->
<!--- under the License. -->
-{#cpp-guide}
-
# C++ Guide
+{#cpp-guide}
+
This guide introduces the tvm-ffi C++ API.
We provide C++ API on top of the stable C ABI to provide a type-safe and
efficient way to work with the tvm-ffi.
The C++ API is designed to abstract away the complexity of the C ABI while
maintaining full compatibility.
@@ -123,6 +123,7 @@ void ExampleObjectPtr() {
We typically provide a reference class that wraps the ObjectPtr.
The `ObjectRef` base class provides the interface and reference counting
functionality for these wrapper classes.
+
```cpp
#include <tvm/ffi/object.h>
#include <tvm/ffi/memory.h>
@@ -152,6 +153,7 @@ void ExampleObjectRef() {
The ObjectRef acts as a smart pointer wrapper that automatically manages the
ObjectPtr lifecycle.
The overall implementation pattern is as follows:
+
- **Object Class**: Inherits from `ffi::Object`, stores data and implements
the core functionality.
- **ObjectPtr**: Smart pointer that manages the Object lifecycle and reference
counting.
- **Ref Class**: Inherits from `ffi::ObjectRef`, provides a user-friendly
interface and automatic memory management.
@@ -181,12 +183,10 @@ This design allows us to allocate the control block and
object memory together.
all of our heap-allocated classes such as Function, on-heap String, Array and
Map are managed using subclasses of Object,
and the user-facing classes such as Function are ObjectRefs.
-
We provide a collection of built-in object and reference types, which are
sufficient for common cases.
Developers can also bring new object types as shown in the example of this
section. We provide mechanisms
to expose these objects to other language bindings such as Python.
-
## Function
The `Function` class provides a type-safe way to create and invoke callable
objects
@@ -230,6 +230,7 @@ void ExampleFunctionFromPacked() {
```
At a high level, `ffi::Function` implements function calling by the following
convention:
+
- The arguments are passed through an on-stack array of `ffi::AnyView`
- Return values are passed through `ffi::Any`
@@ -256,7 +257,6 @@ This pattern is very powerful because we can construct
`ffi::Function` not only
but from any languages that expose to the tvm-ffi ABI. For example, this means
we can easily call functions
passed in or registered from Python for quick debugging or other purposes.
-
### Global Function Registry
Besides creating functions locally, tvm-ffi provides a global function
registry that allows
@@ -325,12 +325,14 @@ void ExampleErrorHandling() {
}
}
```
+
The structured error class records kind, message and backtrace that can be
mapped to
Pythonic style error types and traces. The `TracebackMostRecentCallLast()`
call reverses
the backtrace and print out follows the Python style,
tvm-ffi will try to preserve the backtrace when possible. In the above example,
you can see the output as
-```
+
+```text
... more lines omitted
File "cpp/test_example.cc", line 106, in ExampleErrorHandling
File "cpp/test_example.cc", line 100, in void FuncThrowError()
@@ -342,7 +344,6 @@ So when we call the function from Python, the Error will be
translated into a co
Error type. Similarly, when we call a Python callback from C++, the error will
be translated
into the right error kind and message.
-
## Tensor
For many use cases, we do not need to manage the nd-array/Tensor memory.
@@ -524,7 +525,6 @@ void ExampleMap() {
}
```
-
Under the hood, Map is backed by a reference-counted Object `MapObj` that
stores
a collection of Any values. The implementation provides a SmallMap variant
that stores
values as an array and another variant that is based on a hashmap. The Map
preserves insertion
@@ -559,7 +559,6 @@ void ExampleOptional() {
}
```
-
### Variant
`Variant<Types...>` provides a type-safe union of different types.
diff --git a/docs/guides/packaging.md b/docs/guides/packaging.md
index 3384c05..a50f413 100644
--- a/docs/guides/packaging.md
+++ b/docs/guides/packaging.md
@@ -38,6 +38,7 @@ cd tvm-ffi
The examples are now in the examples folder. You can quickly build
and install the example using the following command.
+
```bash
cd examples/packaging
pip install -v .
@@ -53,7 +54,7 @@ python run_example.py add_one
A typical tvm-ffi-based project has the following structure:
-```
+```text
├── CMakeLists.txt # CMake build configuration
├── pyproject.toml # Python packaging configuration
├── src/
@@ -130,6 +131,7 @@ add_subdirectory(${tvm_ffi_ROOT} tvm_ffi)
# linking the library
target_link_libraries(my_ffi_extension tvm_ffi_shared)
```
+
Note that it is always safe to build from source, and the extra cost of
building tvm-ffi is small
because tvm-ffi is a lightweight library. If you are in doubt,
you can always choose to build tvm-ffi from source.
@@ -235,11 +237,13 @@ def raise_error(msg):
## Build and Use the Package
First, build the wheel:
+
```bash
pip wheel -v -w dist .
```
Then install the built wheel:
+
```bash
pip install dist/*.whl
```
@@ -262,12 +266,13 @@ print(y) # Output: tensor([2., 3., 4., 5., 6.])
You can also run the following command to see how errors are raised and
propagated
across language boundaries:
-```python
+```bash
python run_example.py raise_error
```
When possible, tvm-ffi will try to preserve backtraces across language
boundaries. You will see outputs like:
-```
+
+```text
File "src/extension.cc", line 45, in void
my_ffi_extension::RaiseError(tvm::ffi::String)
```
diff --git a/docs/guides/python_guide.md b/docs/guides/python_guide.md
index 529c030..0fd35d8 100644
--- a/docs/guides/python_guide.md
+++ b/docs/guides/python_guide.md
@@ -195,8 +195,10 @@ test_raise_error =
tvm_ffi.get_global_func("testing.test_raise_error")
test_raise_error("ValueError", "message")
```
+
The above code shows an example where an error is raised in C++, resulting in
the following error trace
-```
+
+```text
Traceback (most recent call last):
File "example.py", line 7, in <module>
test_raise_error("ValueError", "message")
@@ -206,6 +208,7 @@ File "python/tvm_ffi/cython/function.pxi", line 325, in
core.Function.__call__
^^^
File "src/ffi/extra/testing.cc", line 60, in void
tvm::ffi::TestRaiseError(tvm::ffi::String, tvm::ffi::String)
throw ffi::Error(kind, msg, TVMFFITraceback(__FILE__, __LINE__,
TVM_FFI_FUNC_SIG, 0));
+
```
We register common error kinds. You can also register extra error dispatch via
the {py:func}`tvm_ffi.register_error` function.
@@ -276,6 +279,7 @@ test_int_pair = TestIntPair(1, 2)
assert test_int_pair.a == 1
assert test_int_pair.b == 2
```
+
Under the hood, we leverage the information registered through the reflection
registry to
generate efficient field accessors and methods for each class.
diff --git a/examples/packaging/README.md b/examples/packaging/README.md
index ae17107..e7fc95a 100644
--- a/examples/packaging/README.md
+++ b/examples/packaging/README.md
@@ -49,13 +49,15 @@ python run_example.py add_one
You can also run the following command to see how error is raised and
propagated
across the language boundaries.
-```python
+```bash
python run_example.py raise_error
```
When possible, tvm_ffi will try to preserve backtrace across language
boundary. You will see output like
-```
+
+```text
File "src/extension.cc", line 45, in void
my_ffi_extension::RaiseError(tvm::ffi::String)
```
+
If you are in an IDE like VSCode, you can click and jump to the C++ lines of
error when
the debug symbols are preserved.
diff --git a/tests/lint/check_file_type.py b/tests/lint/check_file_type.py
index c776b20..bedc542 100644
--- a/tests/lint/check_file_type.py
+++ b/tests/lint/check_file_type.py
@@ -58,6 +58,7 @@ ALLOW_EXTENSION = {
"yml",
"yaml",
"json",
+ "cfg",
# docs
"txt",
"md",