Use Executorch's Module Extension API on arm64 Mac

I want to run a small MLP in the Executorch runtime (eventually on android, currently on arm64 Mac).
For the start I just cloned the Executorch Repo and set everything up.
I can build and run the executor_runner without problems.
I then started to edit the executor_runner so that it matches my needs.
Problem is, as soon as I start using the Module Extension API, which would ease things, I get the below error when calling Cmake.
I added the module.h to the targets.bzl and #included it in the executor_runner.cpp.

Undefined symbols for architecture arm64:
  "executorch::extension::Module::Module(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, executorch::extension::Module::LoadMode, std::__1::unique_ptr<executorch::runtime::EventTracer, std::__1::default_delete<executorch::runtime::EventTracer>>)", referenced from:
      _main in executor_runner.cpp.o
ld: symbol(s) not found for architecture arm64
c++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [executor_runner] Error 1
make[1]: *** [CMakeFiles/executor_runner.dir/all] Error 2
make: *** [all] Error 2

I am new to Executorch and also not a pro in c++ and Cmake.

Executorch: release/0.4
MacBook Air M3 (arm64)

Hi @simonsasse,

Thanks for trying out ExecuTorch!

The targets.bzl file is for building with Buck; you’ll have to edit the CMakeLists.txt file to build with CMake. You could take a look at the module test as an example: executorch/extension/module/test at main · pytorch/executorch · GitHub

Could you explain more about what you’re trying to do with the Module API / executor_runner? executor_runner uses all the lower-level APIs to load and run a model, whereas Module is a higher-level API that does the same thing. So you probably want to use one or the other.

cc @shoumikhin for Module API.

Hi @lucylq, thank you so much for the quick reply.

I want to use the Module API instead of the lower level APIs used in the executor_runner.

I wrote my own run script before (outside the executorch directory) and ran into the same issue. So I thought I might just try if my Cmake build is missing some reference or so . That’s why I started to edit the executor_runner. It’s basically taken from this tutorial:
https://pytorch.org/executorch/stable/extension-module.html#running-an-executorch-model-using-the-module-extension-in-c

#include <executorch/extension/module/module.h>
#include <executorch/extension/tensor/tensor.h>

#include <cassert>
#include <iostream>

using namespace ::executorch::extension;

int main(int argc, char **argv)
{
    // Create a Module.
    Module module("example/path.pte");

    // Wrap the input data with a Tensor.
    float input[1 * 3];
    auto inTensor = from_blob(input, {1, 3});

    // ......

    // Perform forward
    const auto result = module.forward(inTensor);

    // Check for success or failure.
   // ......
}

Hi @simonsasse, thanks for the additional context.

So executor_runner is built in the root CMakeLists.txt file, set to ON by default.

And Module is built in the root CMakeLists.txt file if EXECUTORCH_BUILD_EXTENSION_MODULE=ON, it is OFF by default.

I think the missing pieces are:

  1. Set EXECUTORCH_BUILD_EXTENSION_MODULE=ON in the root CMakeLists.txt, to build the Module library. This will build the targets extension_module, extension_module_static.
  2. Link extension_module or extension_module_static as a library to your target, eg., target_link_libraries({your_target_name} extension_module)

See this example. It might be better to create a separate CMakeLists.txt file rather than putting it into the root, but hopefully this helps.

1 Like