| # Statically-linked custom module sample for IREE tooling | |
| This sample derives from the [basic](./samples/custom_module/basic/) sample to | |
| show how to build a custom C++ module that can be statically linked into the | |
| IREE command line tools. This is only useful for debugging/developing/profiling | |
| custom modules and is not intended as a deployment mechanism. Once a custom | |
| module has been written it can be statically linked into the user's hosting | |
| runtime application or library or dynamically linked and loaded as with the | |
| [dynamic](./samples/custom_module/dynamic/) sample. | |
| The custom module is implemented using a C++ module wrapper layer in | |
| [`module.cc`](./module.cc) and loaded by the `iree-run-module` tool | |
| automatically whenever any user module depends on it. | |
| ## Background | |
| IREE's VM is used to dynamically link modules of various types together at | |
| runtime (C, C++, IREE's VM bytecode, etc). Via this mechanism any number of | |
| modules containing exported functions and types that can be used across modules | |
| can extend IREE's base functionality. The IREE tooling (`iree-run-module`, | |
| `iree-benchmark-module`, etc) is _not_ an ML runtime and not intended to be | |
| deployed but it can be useful to test custom modules using them in order to | |
| benchmark, profile, or debug outside of user applications. This sample | |
| demonstrates how to take a generic custom module that's effectively identical to | |
| both [basic](./samples/custom_module/basic/) and | |
| [dynamic](./samples/custom_module/dynamic/) samples and link that into the IREE | |
| tools for those purposes. Note that this is mostly about CMake configuration and | |
| matching some tooling-specific function signatures and it's possible to share | |
| the same module code between all various modes with minor differences. | |
| ## Instructions | |
| 1. Build or install the `iree-compile` binary: | |
| ``` | |
| python -m pip install iree-compiler | |
| ``` | |
| [See here](https://openxla.github.io/iree/reference/bindings/python/) | |
| for general instructions on installing the compiler. | |
| 3. Compile the [example module](./test/example.mlir) to a .vmfb file: | |
| ``` | |
| # This simple sample doesn't use tensors and can be compiled in host-only | |
| # mode to avoid the need for the HAL. | |
| iree-compile --iree-hal-target-backends=vmvx samples/custom_module/static/test/example.mlir -o=/tmp/example.vmfb | |
| ``` | |
| 3. Configure the IREE tools to include the custom module: | |
| ``` | |
| cmake -B ../iree-build/ -DCMAKE_BUILD_TYPE=RelWithDebInfo . \ | |
| -DCMAKE_C_FLAGS=-DIREE_VM_EXECUTION_TRACING_FORCE_ENABLE=1 \ | |
| -DIREE_EXTERNAL_TOOLING_MODULES=static_sample \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/samples/custom_module/static \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/samples/custom_module/static \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_TARGET=iree_samples_custom_module_static_module \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_NAME=custom \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_REGISTER_TYPES=register_sample_module_types \ | |
| -DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_CREATE=create_sample_module | |
| cmake --build ../iree-build/ --target iree-run-module | |
| ``` | |
| (here we force runtime execution tracing for demonstration purposes) | |
| [See here](https://openxla.github.io/iree/building-from-source/getting-started/) | |
| for general instructions on building using CMake. | |
| 4. Run the example program using the main `iree-run-module` tool: | |
| ``` | |
| ../iree-build/tools/iree-run-module \ | |
| --module=/tmp/example.vmfb \ | |
| --function=main | |
| ``` | |
| ### Type registration | |
| Custom types defined by the dynamic module must be registered with the | |
| `iree_vm_instance_t` provided to the creation function. | |
| Any externally defined types such as the builtin VM types | |
| (`!vm.list`/`iree_vm_list_t`) or the HAL types | |
| (`!hal.buffer_view`/`iree_hal_buffer_view_t`) must be resolved from the instance | |
| prior to use. `iree_vm_resolve_builtin_types` and | |
| `iree_hal_module_resolve_all_types` (or one of the more restricted sets like | |
| `iree_hal_module_resolve_common_types`) can be used to perform the resolution. | |
| The tooling has a quirk around dynamic module resolution that requires all types | |
| be registered prior to loading modules. Here that is implemented with the | |
| `register_sample_module_types` function that is provided to CMake via | |
| `-DIREE_EXTERNAL_TOOLING_MODULE_STATIC_SAMPLE_REGISTER_TYPES=` to ensure that | |
| the sample types get registered first. In a real application that manually | |
| creates modules this would not be required as modules are expected to manage | |
| type registration alongside their lifetime. |