Change dylib embedding to static library

Replace dylib embedding executables by static library. Also add emitc
static library for float/quant models.

Change-Id: Ibe176bd62f5bfb6084804f7279182b9d66379e99
diff --git a/cmake/springbok_bytecode_module.cmake b/cmake/springbok_bytecode_module.cmake
index e9314de..05e3ab9 100644
--- a/cmake/springbok_bytecode_module.cmake
+++ b/cmake/springbok_bytecode_module.cmake
@@ -14,22 +14,22 @@
 # Examples:
 # springbok_bytecode_module(
 #   NAME
-#     dare_devel_bytecode_module_dylib
+#     daredevel_bytecode_module_static
 #   SRC
 #     "daredevil_quant.tflite"
 #   C_IDENTIFIER
-#     "daredevil_bytecode_module_dylib"
+#     "daredevil_bytecode_module_static"
 #   FLAGS
 #     "-iree-input-type=tosa"
 # )
 #
 # springbok_bytecode_module(
 #   NAME
-#     simple_float_mul_bytecode_module_dylib
+#     simple_float_mul_bytecode_module_static
 #   SRC
 #     "simple_float_mul.mlir"
 #   C_IDENTIFIER
-#     "simple_float_mul_bytecode_module_dylib"
+#     "simple_float_mul_bytecode_module_static"
 #   FLAGS
 #     "-iree-input-type=mhlo"
 #   RVV_OFF
@@ -67,28 +67,91 @@
     )
   endif()
 
+  get_filename_component(_MLIR_SRC "${_MLIR_SRC}" REALPATH)
+  iree_get_executable_path(_TRANSLATE_TOOL_EXECUTABLE "iree-translate")
+  iree_get_executable_path(_LINKER_TOOL_EXECUTABLE "lld")
+
+  # Replace dependencies passed by ::name with iree::package::name
+  iree_package_ns(_PACKAGE_NS)
+  list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
+
+  # Prefix the library with the package name, so we get: iree_package_name.
+  iree_package_name(_PACKAGE_NAME)
+
+  set(_LIB_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")
+  set(_O_FILE_NAME ${_RULE_NAME}.o)
+  set(_H_FILE_NAME ${_RULE_NAME}.h)
+  set(_VMFB_FILE_NAME ${_RULE_NAME}.vmfb)
+
   set(_CPU_FEATURES "+m,+f,+zvl512b,+zve32x")
   if (${_RULE_RVV_OFF})
     set(_CPU_FEATURES "+m,+f")
   endif()
 
-  iree_bytecode_module(
+  ## Example with VM C module.
+  # Setup args for iree-translate.
+  set(_TRANSLATE_ARGS ${_RULE_FLAGS})
+  list(APPEND _TRANSLATE_ARGS "-iree-mlir-to-vm-bytecode-module")
+  list(APPEND _TRANSLATE_ARGS "-iree-hal-target-backends=dylib-llvm-aot")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-target-triple=riscv32-pc-linux-elf")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-target-cpu=generic-rv32")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-target-cpu-features=${_CPU_FEATURES}")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-target-abi=ilp32")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-link-embedded=false")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-link-static")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-system-linker-path=\"${_LINKER_TOOL_EXECUTABLE}\"")
+  list(APPEND _TRANSLATE_ARGS "-iree-llvm-static-library-output-path=${_O_FILE_NAME}")
+  list(APPEND _TRANSLATE_ARGS "${_MLIR_SRC}")
+  list(APPEND _TRANSLATE_ARGS "-o")
+  list(APPEND _TRANSLATE_ARGS "${_VMFB_FILE_NAME}")
+
+  # Custom command for iree-translate to generate static library and C module.
+  add_custom_command(
+    OUTPUT
+      ${_H_FILE_NAME}
+      ${_O_FILE_NAME}
+      ${_VMFB_FILE_NAME}
+    COMMAND ${_TRANSLATE_TOOL_EXECUTABLE} ${_TRANSLATE_ARGS}
+    DEPENDS ${_TRANSLATE_TOOL_EXECUTABLE} ${_MLIR_SRC} ${_LINKER_TOOL_EXECUTABLE}
+  )
+
+  add_library(${_LIB_NAME}
+    STATIC
+    ${_O_FILE_NAME}
+  )
+
+  SET_TARGET_PROPERTIES(
+    ${_LIB_NAME}
+    PROPERTIES
+    LINKER_LANGUAGE C
+  )
+
+  # Alias the iree_package_name library to iree::package::name.
+  # This lets us more clearly map to Bazel and makes it possible to
+  # disambiguate the underscores in paths vs. the separators.
+  add_library(${_PACKAGE_NS}::${_RULE_NAME} ALIAS ${_LIB_NAME})
+  iree_package_dir(_PACKAGE_DIR)
+  if(${_RULE_NAME} STREQUAL ${_PACKAGE_DIR})
+    add_library(${_PACKAGE_NS} ALIAS ${_LIB_NAME})
+  endif()
+
+  set(_RULE_C_NAME "${_RULE_NAME}_c")
+  set(_H_FILE_NAME ${_RULE_C_NAME}.h)
+  set(_C_FILE_NAME ${_RULE_C_NAME}.c)
+
+  # Generate the embed data with the bytecode module
+  iree_c_embed_data(
     NAME
-      "${_RULE_NAME}"
-    SRC
-      "${_MLIR_SRC}"
-    C_IDENTIFIER
+      "${_RULE_C_NAME}"
+    IDENTIFIER
       "${_RULE_C_IDENTIFIER}"
-    FLAGS
-      "-iree-mlir-to-vm-bytecode-module"
-      "-iree-hal-target-backends=dylib-llvm-aot"
-      "-iree-llvm-target-triple=riscv32-pc-linux-elf"
-      "-iree-llvm-target-cpu=generic-rv32"
-      "-iree-llvm-target-cpu-features=${_CPU_FEATURES}"
-      "-iree-llvm-target-abi=ilp32"
-      "-iree-llvm-link-embedded=true"
-      "-iree-llvm-debug-symbols=false"
-      "${_RULE_FLAGS}"
+    GENERATED_SRCS
+      "${_VMFB_FILE_NAME}"
+    C_FILE_OUTPUT
+      "${_C_FILE_NAME}"
+    H_FILE_OUTPUT
+      "${_H_FILE_NAME}"
+    FLATTEN
     PUBLIC
   )
 endfunction()
diff --git a/cmake/springbok_modules.cmake b/cmake/springbok_modules.cmake
index a410525..30d3a40 100644
--- a/cmake/springbok_modules.cmake
+++ b/cmake/springbok_modules.cmake
@@ -18,7 +18,7 @@
 #   SRC
 #     "daredevil_quant.tflite"
 #   C_IDENTIFIER
-#     "daredevil_bytecode_module_dylib"
+#     "daredevil_bytecode_module_static"
 #   FLAGS
 #     "-iree-input-type=tosa"
 # )
@@ -52,11 +52,11 @@
 
   springbok_bytecode_module(
     NAME
-      "${_RULE_NAME}_bytecode_module_dylib"
+      "${_RULE_NAME}_bytecode_module_static"
     SRC
       "${_RULE_SRC}"
     C_IDENTIFIER
-      "${_RULE_C_IDENTIFIER}_bytecode_module_dylib"
+      "${_RULE_C_IDENTIFIER}_bytecode_module_static"
     FLAGS
       "${_RULE_FLAGS}"
     "${_RVV_OFF_ARG}"
diff --git a/samples/device/CMakeLists.txt b/samples/device/CMakeLists.txt
index cec04b0..8aa809a 100644
--- a/samples/device/CMakeLists.txt
+++ b/samples/device/CMakeLists.txt
@@ -1,20 +1,5 @@
 iree_cc_library(
   NAME
-    device_embedded_sync
-  HDRS
-    "device.h"
-  SRCS
-    "device_embedded_sync.c"
-  DEPS
-    iree::base
-    iree::hal
-    iree::hal::local
-    iree::hal::local::loaders::embedded_library_loader
-    iree::hal::local::sync_driver
-)
-
-iree_cc_library(
-  NAME
     device_static_loader
   HDRS
     "device.h"
diff --git a/samples/device/device_embedded_sync.c b/samples/device/device_embedded_sync.c
deleted file mode 100644
index f511098..0000000
--- a/samples/device/device_embedded_sync.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// An example of setting up the embedded-sync driver.
-
-#include <stddef.h>
-
-#include "iree/hal/local/executable_loader.h"
-#include "iree/hal/local/loaders/embedded_library_loader.h"
-#include "iree/hal/local/sync_device.h"
-#include "samples/device/device.h"
-
-iree_status_t create_sample_device(iree_allocator_t host_allocator,
-                                   iree_hal_device_t** out_device) {
-  // Set parameters for the device created in the next step.
-  iree_hal_sync_device_params_t params;
-  iree_hal_sync_device_params_initialize(&params);
-
-  iree_hal_executable_loader_t* loader = NULL;
-  IREE_RETURN_IF_ERROR(iree_hal_embedded_library_loader_create(
-      iree_hal_executable_import_provider_null(), host_allocator, &loader));
-
-  // Use the default host allocator for buffer allocations.
-  iree_string_view_t identifier = iree_make_cstring_view("dylib");
-  iree_hal_allocator_t* device_allocator = NULL;
-  iree_status_t status = iree_hal_allocator_create_heap(
-      identifier, host_allocator, host_allocator, &device_allocator);
-
-  // Create the synchronous device and release the loader afterwards.
-  if (iree_status_is_ok(status)) {
-    status = iree_hal_sync_device_create(
-        identifier, &params, /*loader_count=*/1, &loader, device_allocator,
-        host_allocator, out_device);
-  }
-
-  iree_hal_allocator_release(device_allocator);
-  iree_hal_executable_loader_release(loader);
-  return status;
-}
diff --git a/samples/float_model/CMakeLists.txt b/samples/float_model/CMakeLists.txt
index b904296..3ada748 100644
--- a/samples/float_model/CMakeLists.txt
+++ b/samples/float_model/CMakeLists.txt
@@ -3,33 +3,35 @@
 # are for RVV support.
 #-------------------------------------------------------------------------------
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    mobilenet_v1_bytecode_module_dylib
+    mobilenet_v1
   SRC
     "$ENV{ROOTDIR}/ml/ml-models-public/float_models/mobilenet_v1_0.25_224_float.tflite"
   C_IDENTIFIER
-    "samples_float_model_mobilenet_v1_bytecode_module_dylib"
+    "samples_float_model_mobilenet_v1"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
     "-riscv-v-fixed-length-vector-lmul-max=8"
     "-riscv-v-fixed-length-vector-elen-max=32"
+  RVV_OFF
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    mnist_bytecode_module_dylib
+    mnist
   SRC
     "$ENV{ROOTDIR}/toolchain/iree/iree/samples/models/mnist.mlir"
   C_IDENTIFIER
-    "samples_float_model_mnist_bytecode_module_dylib"
+    "samples_float_model_mnist"
   FLAGS
     "-iree-input-type=mhlo"
     "-riscv-v-vector-bits-min=512"
     "-riscv-v-fixed-length-vector-lmul-max=8"
     "-riscv-v-fixed-length-vector-elen-max=32"
+  RVV_OFF
   PUBLIC
 )
 
@@ -73,12 +75,14 @@
 
 iree_cc_binary(
   NAME
-    mobilenet_v1_embedded_sync
+    mobilenet_v1_bytecode_static
   SRCS
     "mobilenet_v1.c"
   DEPS
-    ::mobilenet_v1_bytecode_module_dylib_c
+    ::mobilenet_v1_bytecode_module_static
+    ::mobilenet_v1_bytecode_module_static_c
     ::mobilenet_input_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=200k"
@@ -86,13 +90,49 @@
 
 iree_cc_binary(
   NAME
-    mnist_embedded_sync
+    mobilenet_v1_emitc_static
+  SRCS
+    "mobilenet_v1.c"
+  DEPS
+    ::mobilenet_v1_c_module_static_c
+    ::mobilenet_v1_c_module_static_emitc
+    ::mobilenet_input_c
+    samples::util::util
+    "m"
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=200k"
+  COPTS
+    "-DBUILD_EMITC"
+)
+
+iree_cc_binary(
+  NAME
+    mnist_bytecode_static
   SRCS
     "mnist.c"
   DEPS
-    ::mnist_bytecode_module_dylib_c
+    ::mnist_bytecode_module_static
+    ::mnist_bytecode_module_static_c
     ::mnist_input_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=100k"
 )
+
+iree_cc_binary(
+  NAME
+    mnist_emitc_static
+  SRCS
+    "mnist.c"
+  DEPS
+    ::mnist_c_module_static_c
+    ::mnist_c_module_static_emitc
+    ::mnist_input_c
+    samples::util::util
+    "m"
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+  COPTS
+    "-DBUILD_EMITC"
+)
diff --git a/samples/float_model/mnist.c b/samples/float_model/mnist.c
index 5c7e874..7cccb9f 100644
--- a/samples/float_model/mnist.c
+++ b/samples/float_model/mnist.c
@@ -10,7 +10,13 @@
 #include "mnist.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/float_model/mnist_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/float_model/mnist_bytecode_module_static.h"
+#include "samples/float_model/mnist_bytecode_module_static_c.h"
+#else
+#include "samples/float_model/mnist_c_module_static_c.h"
+#include "samples/float_model/mnist_c_module_static_emitc.h"
+#endif
 #include "samples/float_model/mnist_input_c.h"
 
 const MlModel kModel = {
@@ -29,11 +35,22 @@
 
 MnistOutput score;
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_float_model_mnist_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_float_model_mnist_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+  return mnist_linked_llvm_library_query(max_version,
+                                         /*reserved=*/reserved);
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -45,8 +62,8 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
   // find the label index with best prediction
   float best_out = 0.0;
diff --git a/samples/float_model/mobilenet_v1.c b/samples/float_model/mobilenet_v1.c
index 4b610fd..c9a72d0 100644
--- a/samples/float_model/mobilenet_v1.c
+++ b/samples/float_model/mobilenet_v1.c
@@ -11,7 +11,13 @@
 
 // Compiled module embedded here to avoid file IO:
 #include "samples/float_model/mobilenet_input_c.h"
-#include "samples/float_model/mobilenet_v1_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/float_model/mobilenet_v1_bytecode_module_static.h"
+#include "samples/float_model/mobilenet_v1_bytecode_module_static_c.h"
+#else
+#include "samples/float_model/mobilenet_v1_c_module_static_c.h"
+#include "samples/float_model/mobilenet_v1_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -29,23 +35,42 @@
 
 MobilenetV1Output score;
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_float_model_mobilenet_v1_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_float_model_mobilenet_v1_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
 }
 
-iree_status_t load_input_data(const MlModel *model, void **buffer, iree_byte_span_t **byte_span) {
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return mobilenet_v1_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return mobilenet_v1_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
+}
+
+iree_status_t load_input_data(const MlModel *model, void **buffer,
+                              iree_byte_span_t **byte_span) {
   byte_span[0] = malloc(sizeof(iree_byte_span_t));
-  *byte_span[0] = iree_make_byte_span(mobilenet_input, model->input_size_bytes[0] *
-                                                  model->input_length[0]);
+  *byte_span[0] = iree_make_byte_span(
+      mobilenet_input, model->input_size_bytes[0] * model->input_length[0]);
   return iree_ok_status();
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
   // find the label index with best prediction
   float best_out = 0.0;
diff --git a/samples/quant_model/CMakeLists.txt b/samples/quant_model/CMakeLists.txt
index 91d3250..3d2a3b6 100644
--- a/samples/quant_model/CMakeLists.txt
+++ b/samples/quant_model/CMakeLists.txt
@@ -3,30 +3,13 @@
 # are for RVV support.
 #-------------------------------------------------------------------------------
 
-if(NOT ${BUILD_WITH_SPRINGBOK})
-  springbok_bytecode_module(
-    NAME
-      mobilenet_v2_bytecode_module_dylib
-    SRC
-      "$ENV{ROOTDIR}/ml/ml-models-public/quant_models/mobilenet_v2_1.0_224_quant.tflite"
-    C_IDENTIFIER
-      "samples_quant_model_mobilenet_v2_bytecode_module_dylib"
-    FLAGS
-      "-iree-input-type=tosa"
-      "-riscv-v-vector-bits-min=512"
-      "-riscv-v-fixed-length-vector-lmul-max=8"
-      "-riscv-v-fixed-length-vector-elen-max=32"
-    PUBLIC
-  )
-endif()
-
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    mobilenet_v1_bytecode_module_dylib
+    mobilenet_v1
   SRC
     "$ENV{ROOTDIR}/ml/ml-models-public/quant_models/mobilenet_v1_0.25_224_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_mobilenet_v1_bytecode_module_dylib"
+    "samples_quant_model_mobilenet_v1"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -35,13 +18,28 @@
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    person_detection_bytecode_module_dylib
+    mobilenet_v2
+  SRC
+    "$ENV{ROOTDIR}/ml/ml-models-public/quant_models/mobilenet_v2_1.0_224_quant.tflite"
+  C_IDENTIFIER
+    "samples_quant_model_mobilenet_v2"
+  FLAGS
+    "-iree-input-type=tosa"
+    "-riscv-v-vector-bits-min=512"
+    "-riscv-v-fixed-length-vector-lmul-max=8"
+    "-riscv-v-fixed-length-vector-elen-max=32"
+  PUBLIC
+)
+
+springbok_modules(
+  NAME
+    person_detection
   SRC
     "$ENV{ROOTDIR}/ml/ml-models-public/quant_models/person_detection.tflite"
   C_IDENTIFIER
-    "samples_quant_model_person_detection_bytecode_module_dylib"
+    "samples_quant_model_person_detection"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -52,30 +50,13 @@
 
 if(${BUILD_INTERNAL_MODELS})
 
-if(NOT ${BUILD_WITH_SPRINGBOK})
-  springbok_bytecode_module(
-    NAME
-      scenenet_v2_bytecode_module_dylib
-    SRC
-      "$ENV{ROOTDIR}/ml/ml-models/quant_models/scenenet_v2_quant.tflite"
-    C_IDENTIFIER
-      "samples_quant_model_scenenet_v2_bytecode_module_dylib"
-    FLAGS
-      "-iree-input-type=tosa"
-      "-riscv-v-vector-bits-min=512"
-      "-riscv-v-fixed-length-vector-lmul-max=8"
-      "-riscv-v-fixed-length-vector-elen-max=32"
-    PUBLIC
-  )
-endif()
-
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    barcode_bytecode_module_dylib
+    barcode
   SRC
     "$ENV{ROOTDIR}/ml/ml-models/quant_models/barcode_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_barcode_bytecode_module_dylib"
+    "samples_quant_model_barcode"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -84,13 +65,13 @@
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    daredevil_bytecode_module_dylib
+    daredevil
   SRC
     "$ENV{ROOTDIR}/ml/ml-models/quant_models/daredevil_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_daredevil_bytecode_module_dylib"
+    "samples_quant_model_daredevil"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -99,13 +80,13 @@
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    fssd_25_8bit_v2_bytecode_module_dylib
+    fssd_25_8bit_v2
   SRC
     "$ENV{ROOTDIR}/ml/ml-models/quant_models/fssd_25_8bit_v2_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_fssd_25_8bit_v2_bytecode_module_dylib"
+    "samples_quant_model_fssd_25_8bit_v2"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -114,13 +95,28 @@
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    semantic_lift_bytecode_module_dylib
+    scenenet_v2
+  SRC
+    "$ENV{ROOTDIR}/ml/ml-models/quant_models/scenenet_v2_quant.tflite"
+  C_IDENTIFIER
+    "samples_quant_model_scenenet_v2"
+  FLAGS
+    "-iree-input-type=tosa"
+    "-riscv-v-vector-bits-min=512"
+    "-riscv-v-fixed-length-vector-lmul-max=8"
+    "-riscv-v-fixed-length-vector-elen-max=32"
+  PUBLIC
+)
+
+springbok_modules(
+  NAME
+    semantic_lift
   SRC
     "$ENV{ROOTDIR}/ml/ml-models/quant_models/semantic_lift_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_semantic_lift_bytecode_module_dylib"
+    "samples_quant_model_semantic_lift"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -129,13 +125,13 @@
   PUBLIC
 )
 
-springbok_bytecode_module(
+springbok_modules(
   NAME
-    voice_commands_bytecode_module_dylib
+    voice_commands
   SRC
     "$ENV{ROOTDIR}/ml/ml-models/quant_models/voice_commands_quant.tflite"
   C_IDENTIFIER
-    "samples_quant_model_voice_commands_bytecode_module_dylib"
+    "samples_quant_model_voice_commands"
   FLAGS
     "-iree-input-type=tosa"
     "-riscv-v-vector-bits-min=512"
@@ -184,29 +180,16 @@
 #
 # to increase it.
 
-if(NOT ${BUILD_WITH_SPRINGBOK})
-  iree_cc_binary(
-    NAME
-      mobilenet_v2_embedded_sync
-    SRCS
-      "mobilenet_v2.c"
-    DEPS
-      ::mobilenet_quant_input_c
-      ::mobilenet_v2_bytecode_module_dylib_c
-      samples::util::util
-    LINKOPTS
-      "LINKER:--defsym=__stack_size__=150k"
-  )
-endif()
-
 iree_cc_binary(
   NAME
-    mobilenet_v1_embedded_sync
+    mobilenet_v1_bytecode_static
   SRCS
     "mobilenet_v1.c"
   DEPS
-    ::mobilenet_v1_bytecode_module_dylib_c
     ::mobilenet_quant_input_c
+    ::mobilenet_v1_bytecode_module_static
+    ::mobilenet_v1_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=100k"
@@ -214,52 +197,126 @@
 
 iree_cc_binary(
   NAME
-    person_detection_embedded_sync
+    mobilenet_v1_emitc_static
+  SRCS
+    "mobilenet_v1.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v1_c_module_static_c
+    ::mobilenet_v1_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+  COPTS
+    "-DBUILD_EMITC"
+)
+
+iree_cc_binary(
+  NAME
+    mobilenet_v2_bytecode_static
+  SRCS
+    "mobilenet_v2.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v2_bytecode_module_static
+    ::mobilenet_v2_bytecode_module_static_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+  "LINKER:--defsym=__stack_size__=150k"
+)
+
+iree_cc_binary(
+  NAME
+    mobilenet_v2_emitc_static
+  SRCS
+    "mobilenet_v2.c"
+  DEPS
+    ::mobilenet_quant_input_c
+    ::mobilenet_v2_c_module_static_c
+    ::mobilenet_v2_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=150k"
+  COPTS
+    "-DBUILD_EMITC"
+)
+
+iree_cc_binary(
+  NAME
+    person_detection_bytecode_static
   SRCS
     "person_detection.c"
   DEPS
-    ::person_detection_bytecode_module_dylib_c
+    ::person_detection_bytecode_module_static
+    ::person_detection_bytecode_module_static_c
+    ::person_detection_quant_input_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=128k"
+)
+
+iree_cc_binary(
+  NAME
+    person_detection_emitc_static
+  SRCS
+    "person_detection.c"
+  DEPS
+    ::person_detection_c_module_static_c
+    ::person_detection_c_module_static_emitc
     ::person_detection_quant_input_c
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=128k"
+  COPTS
+    "-DBUILD_EMITC"
 )
 
 if(NOT ${BUILD_INTERNAL_MODELS})
   return()
 endif()
 
-if(NOT ${BUILD_WITH_SPRINGBOK})
-  iree_cc_binary(
-    NAME
-      scenenet_v2_embedded_sync
-    SRCS
-      "scenenet_v2.c"
-    DEPS
-      ::scenenet_v2_bytecode_module_dylib_c
-      samples::util::util
-  )
-endif()
-
 iree_cc_binary(
   NAME
-    barcode_embedded_sync
+    barcode_bytecode_static
   SRCS
     "barcode.c"
   DEPS
-    ::barcode_bytecode_module_dylib_c
+    ::barcode_bytecode_module_static
+    ::barcode_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
+    "LINKER:--defsym=__itcm_length__=700k"
     "LINKER:--defsym=__stack_size__=100k"
 )
 
+#iree_cc_binary(
+#  NAME
+#    barcode_emitc_static
+#  SRCS
+#    "barcode.c"
+#  DEPS
+#    ::barcode_c_module_static_c
+#    ::barcode_c_module_static_emitc
+#    samples::util::util
+#  LINKOPTS
+#    "LINKER:--defsym=__itcm_length__=700k"
+#    "LINKER:--defsym=__stack_size__=100k"
+#  COPTS
+#    "-DBUILD_EMITC"
+#)
+
 iree_cc_binary(
   NAME
-    daredevil_embedded_sync
+    daredevil_bytecode_static
   SRCS
     "daredevil.c"
   DEPS
-    ::daredevil_bytecode_module_dylib_c
+    ::daredevil_bytecode_module_static
+    ::daredevil_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=100k"
@@ -267,36 +324,131 @@
 
 iree_cc_binary(
   NAME
-    fssd_25_8bit_v2_embedded_sync
+    daredevil_emitc_static
+  SRCS
+    "daredevil.c"
+  DEPS
+    ::daredevil_c_module_static_c
+    ::daredevil_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+  COPTS
+    "-DBUILD_EMITC"
+)
+
+iree_cc_binary(
+  NAME
+    fssd_25_8bit_v2_bytecode_static
   SRCS
     "fssd_25_8bit_v2.c"
   DEPS
-    ::fssd_25_8bit_v2_bytecode_module_dylib_c
+    ::fssd_25_8bit_v2_bytecode_module_static
+    ::fssd_25_8bit_v2_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=100k"
 )
 
+#iree_cc_binary(
+#  NAME
+#    fssd_25_8bit_v2_emitc_static
+#  SRCS
+#    "fssd_25_8bit_v2.c"
+#  DEPS
+#    ::fssd_25_8bit_v2_c_module_static_c
+#    ::fssd_25_8bit_v2_c_module_static_emitc
+#    samples::util::util
+#  LINKOPTS
+#    "LINKER:--defsym=__stack_size__=100k"
+#  COPTS
+#    "-DBUILD_EMITC"
+#)
+
 iree_cc_binary(
   NAME
-    semantic_lift_embedded_sync
+    scenenet_v2_bytecode_static
   SRCS
-    "semantic_lift.c"
+    "scenenet_v2.c"
   DEPS
-    ::semantic_lift_bytecode_module_dylib_c
+    ::scenenet_v2_bytecode_module_static
+    ::scenenet_v2_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
-    "LINKER:--defsym=__stack_size__=20k"
+    "LINKER:--defsym=__stack_size__=150k"
 )
 
 iree_cc_binary(
   NAME
-    voice_commands_embedded_sync
+    scenenet_v2_emitc_static
+  SRCS
+    "scenenet_v2.c"
+  DEPS
+    ::scenenet_v2_c_module_static_c
+    ::scenenet_v2_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=150k"
+  COPTS
+    "-DBUILD_EMITC"
+)
+
+iree_cc_binary(
+  NAME
+    semantic_lift_bytecode_static
+  SRCS
+    "semantic_lift.c"
+  DEPS
+    ::semantic_lift_bytecode_module_static
+    ::semantic_lift_bytecode_module_static_c
+    iree::vm::bytecode_module
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=100k"
+)
+
+#iree_cc_binary(
+#  NAME
+#    semantic_lift_emitc_static
+#  SRCS
+#    "semantic_lift.c"
+#  DEPS
+#    ::semantic_lift_c_module_static_c
+#    ::semantic_lift_c_module_static_emitc
+#    samples::util::util
+#  LINKOPTS
+#    "LINKER:--defsym=__stack_size__=100k"
+#  COPTS
+#    "-DBUILD_EMITC"
+#)
+
+iree_cc_binary(
+  NAME
+    voice_commands_bytecode_static
   SRCS
     "voice_commands.c"
   DEPS
-    ::voice_commands_bytecode_module_dylib_c
+    ::voice_commands_bytecode_module_static
+    ::voice_commands_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
-    "LINKER:--defsym=__stack_size__=64k"
+    "LINKER:--defsym=__stack_size__=150k"
+)
+
+iree_cc_binary(
+  NAME
+    voice_commands_emitc_static
+  SRCS
+    "voice_commands.c"
+  DEPS
+    ::voice_commands_c_module_static_c
+    ::voice_commands_c_module_static_emitc
+    samples::util::util
+  LINKOPTS
+    "LINKER:--defsym=__stack_size__=150k"
+  COPTS
+    "-DBUILD_EMITC"
 )
diff --git a/samples/quant_model/barcode.c b/samples/quant_model/barcode.c
index d70733c..12cf54c 100644
--- a/samples/quant_model/barcode.c
+++ b/samples/quant_model/barcode.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/barcode_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/barcode_bytecode_module_static.h"
+#include "samples/quant_model/barcode_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/barcode_c_module_static_c.h"
+#include "samples/quant_model/barcode_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -27,11 +33,29 @@
     .model_name = "barcode_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_barcode_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_barcode_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return barcode_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return barcode_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -51,7 +75,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/quant_model/daredevil.c b/samples/quant_model/daredevil.c
index d4cb0ac..86ff0fb 100644
--- a/samples/quant_model/daredevil.c
+++ b/samples/quant_model/daredevil.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/daredevil_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/daredevil_bytecode_module_static.h"
+#include "samples/quant_model/daredevil_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/daredevil_c_module_static_c.h"
+#include "samples/quant_model/daredevil_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -25,11 +31,29 @@
     .model_name = "daredevil_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_daredevil_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_daredevil_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return daredevil_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return daredevil_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -49,7 +73,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/quant_model/fssd_25_8bit_v2.c b/samples/quant_model/fssd_25_8bit_v2.c
index 4070c81..7a272da 100644
--- a/samples/quant_model/fssd_25_8bit_v2.c
+++ b/samples/quant_model/fssd_25_8bit_v2.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/fssd_25_8bit_v2_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/fssd_25_8bit_v2_bytecode_module_static.h"
+#include "samples/quant_model/fssd_25_8bit_v2_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/fssd_25_8bit_v2_c_module_static_c.h"
+#include "samples/quant_model/fssd_25_8bit_v2_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -26,11 +32,29 @@
     .model_name = "fssd_25_8bit_v2_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_fssd_25_8bit_v2_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_fssd_25_8bit_v2_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return fssd_25_8bit_v2_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return fssd_25_8bit_v2_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -50,7 +74,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/quant_model/mobilenet_v1.c b/samples/quant_model/mobilenet_v1.c
index 5640c5e..248d81f 100644
--- a/samples/quant_model/mobilenet_v1.c
+++ b/samples/quant_model/mobilenet_v1.c
@@ -6,12 +6,18 @@
 
 #include "iree/base/api.h"
 #include "iree/hal/api.h"
-#include "samples/util/util.h"
 #include "mobilenet_v1.h"
+#include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
 #include "samples/quant_model/mobilenet_quant_input_c.h"
-#include "samples/quant_model/mobilenet_v1_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/mobilenet_v1_bytecode_module_static.h"
+#include "samples/quant_model/mobilenet_v1_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/mobilenet_v1_c_module_static_c.h"
+#include "samples/quant_model/mobilenet_v1_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -29,11 +35,29 @@
 
 MobilenetV1Output score;
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_mobilenet_v1_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_mobilenet_v1_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return mobilenet_v1_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return mobilenet_v1_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -46,8 +70,8 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
   // find the label index with best prediction
   int best_out = 0;
diff --git a/samples/quant_model/mobilenet_v2.c b/samples/quant_model/mobilenet_v2.c
index 8a05907..711937d 100644
--- a/samples/quant_model/mobilenet_v2.c
+++ b/samples/quant_model/mobilenet_v2.c
@@ -11,7 +11,13 @@
 
 // Compiled module embedded here to avoid file IO:
 #include "samples/quant_model/mobilenet_quant_input_c.h"
-#include "samples/quant_model/mobilenet_v2_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/mobilenet_v2_bytecode_module_static.h"
+#include "samples/quant_model/mobilenet_v2_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/mobilenet_v2_c_module_static_c.h"
+#include "samples/quant_model/mobilenet_v2_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -27,14 +33,32 @@
     .model_name = "mobilenet_v2_1.0_224_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+MobilenetV2Output score;
+
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_mobilenet_v2_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_mobilenet_v2_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
 }
 
-MobilenetV2Output score;
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return mobilenet_v2_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return mobilenet_v2_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
+}
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
                               iree_byte_span_t **byte_span) {
@@ -46,8 +70,8 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
   // find the label index with best prediction
   int best_out = 0;
diff --git a/samples/quant_model/person_detection.c b/samples/quant_model/person_detection.c
index 379eb0f..1ef7f56 100644
--- a/samples/quant_model/person_detection.c
+++ b/samples/quant_model/person_detection.c
@@ -10,7 +10,13 @@
 #include "person_detection.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/person_detection_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/person_detection_bytecode_module_static.h"
+#include "samples/quant_model/person_detection_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/person_detection_c_module_static_c.h"
+#include "samples/quant_model/person_detection_c_module_static_emitc.h"
+#endif
 #include "samples/quant_model/person_detection_quant_input_c.h"
 
 const MlModel kModel = {
@@ -29,11 +35,29 @@
 
 PersonDetectionOutput detection;
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_person_detection_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_person_detection_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return person_detection_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return person_detection_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -46,16 +70,15 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
   int8_t *data = (int8_t *)buffers[0].contents.data;
   detection.non_person_score = data[0];
   detection.person_score = data[1];
 
   LOG_INFO("Output: Non-person Score: %d; Person Score: %d",
-            detection.non_person_score,
-            detection.person_score);
+           detection.non_person_score, detection.person_score);
   output->result = &detection;
   output->len = sizeof(detection);
 
diff --git a/samples/quant_model/scenenet_v2.c b/samples/quant_model/scenenet_v2.c
index da680f7..ac5f01f 100644
--- a/samples/quant_model/scenenet_v2.c
+++ b/samples/quant_model/scenenet_v2.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/scenenet_v2_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/scenenet_v2_bytecode_module_static.h"
+#include "samples/quant_model/scenenet_v2_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/scenenet_v2_c_module_static_c.h"
+#include "samples/quant_model/scenenet_v2_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -25,11 +31,29 @@
     .model_name = "scenenet_v2_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_scenenet_v2_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_scenenet_v2_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return scenenet_v2_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return scenenet_v2_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -49,7 +73,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/quant_model/semantic_lift.c b/samples/quant_model/semantic_lift.c
index 973bc0b..5abaff2 100644
--- a/samples/quant_model/semantic_lift.c
+++ b/samples/quant_model/semantic_lift.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/semantic_lift_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/semantic_lift_bytecode_module_static.h"
+#include "samples/quant_model/semantic_lift_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/semantic_lift_c_module_static_c.h"
+#include "samples/quant_model/semantic_lift_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -25,11 +31,29 @@
     .model_name = "semantic_lift_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_semantic_lift_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_semantic_lift_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return semantic_lift_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return semantic_lift_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -49,7 +73,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/quant_model/voice_commands.c b/samples/quant_model/voice_commands.c
index 18b06a7..e7bdf99 100644
--- a/samples/quant_model/voice_commands.c
+++ b/samples/quant_model/voice_commands.c
@@ -9,7 +9,13 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#include "samples/quant_model/voice_commands_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/quant_model/voice_commands_bytecode_module_static.h"
+#include "samples/quant_model/voice_commands_bytecode_module_static_c.h"
+#else
+#include "samples/quant_model/voice_commands_c_module_static_c.h"
+#include "samples/quant_model/voice_commands_c_module_static_emitc.h"
+#endif
 
 const MlModel kModel = {
     .num_input = 1,
@@ -25,11 +31,29 @@
     .model_name = "voice_commands_quant",
 };
 
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_quant_model_voice_commands_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
+      samples_quant_model_voice_commands_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
+#else
+  return module_create(iree_allocator_system(), module);
+#endif
+}
+
+const iree_hal_executable_library_header_t **library_query(
+    iree_hal_executable_library_version_t max_version, void *reserved) {
+#if !defined(BUILD_EMITC)
+  return voice_commands_bytecode_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#else
+  return voice_commands_c_module_static_linked_llvm_library_query(
+      max_version,
+      /*reserved=*/reserved);
+#endif
 }
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
@@ -49,7 +73,7 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                              iree_hal_buffer_mapping_t *buffers,
-                              MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   return iree_ok_status();
 }
diff --git a/samples/simple_vec_mul/CMakeLists.txt b/samples/simple_vec_mul/CMakeLists.txt
index c4bcd03..0b5ff77 100644
--- a/samples/simple_vec_mul/CMakeLists.txt
+++ b/samples/simple_vec_mul/CMakeLists.txt
@@ -48,11 +48,13 @@
 
 iree_cc_binary(
   NAME
-    simple_float_vec_mul_embedded_sync
+    simple_float_vec_mul_bytecode_static
   SRCS
     "float_vec.c"
   DEPS
-    ::simple_float_mul_bytecode_module_dylib_c
+    ::simple_float_mul_bytecode_module_static
+    ::simple_float_mul_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=20k"
@@ -66,20 +68,22 @@
   DEPS
     ::simple_float_mul_c_module_static_c
     ::simple_float_mul_c_module_static_emitc
-    samples::util::util_emitc
+    samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=20k"
   COPTS
-    "-DBUILD_EMITC_STATIC"
+    "-DBUILD_EMITC"
 )
 
 iree_cc_binary(
   NAME
-    simple_int_vec_mul_embedded_sync
+    simple_int_vec_mul_bytecode_static
   SRCS
     "int_vec.c"
   DEPS
-    ::simple_int_mul_bytecode_module_dylib_c
+    ::simple_int_mul_bytecode_module_static
+    ::simple_int_mul_bytecode_module_static_c
+    iree::vm::bytecode_module
     samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=20k"
@@ -93,9 +97,9 @@
   DEPS
     ::simple_int_mul_c_module_static_c
     ::simple_int_mul_c_module_static_emitc
-    samples::util::util_emitc
+    samples::util::util
   LINKOPTS
     "LINKER:--defsym=__stack_size__=20k"
   COPTS
-    "-DBUILD_EMITC_STATIC"
+    "-DBUILD_EMITC"
 )
diff --git a/samples/simple_vec_mul/float_vec.c b/samples/simple_vec_mul/float_vec.c
index 1d4a2d1..d9c53dd 100644
--- a/samples/simple_vec_mul/float_vec.c
+++ b/samples/simple_vec_mul/float_vec.c
@@ -5,8 +5,9 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#if !defined(BUILD_EMITC_STATIC)
-#include "samples/simple_vec_mul/simple_float_mul_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "samples/simple_vec_mul/simple_float_mul_bytecode_module_static.h"
+#include "samples/simple_vec_mul/simple_float_mul_bytecode_module_static_c.h"
 #else
 #include "samples/simple_vec_mul/simple_float_mul_c_module_static_c.h"
 #include "samples/simple_vec_mul/simple_float_mul_c_module_static_emitc.h"
@@ -26,17 +27,16 @@
     .model_name = "simple_float_vec_mul",
 };
 
-#if !defined(BUILD_EMITC_STATIC)
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_simple_vec_mul_simple_float_mul_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
-}
+      samples_simple_vec_mul_simple_float_mul_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
 #else
-// Function to create the C module.
-iree_status_t create_c_module(iree_vm_module_t **module) {
   return module_create(iree_allocator_system(), module);
+#endif
 }
 
 const iree_hal_executable_library_header_t **library_query(
@@ -44,7 +44,6 @@
   return simple_mul_dispatch_0_library_query(max_version,
                                              /*reserved=*/reserved);
 }
-#endif
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
                               iree_byte_span_t **byte_span) {
@@ -67,11 +66,10 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
-  for (int i = 0; i < buffers[0].contents.data_length / sizeof(float);
-       ++i) {
+  for (int i = 0; i < buffers[0].contents.data_length / sizeof(float); ++i) {
     if (((const float *)buffers[0].contents.data)[i] != i * i / 8.0f) {
       result = iree_make_status(IREE_STATUS_UNKNOWN, "result mismatches");
       break;
diff --git a/samples/simple_vec_mul/int_vec.c b/samples/simple_vec_mul/int_vec.c
index 7a78c81..01019e3 100644
--- a/samples/simple_vec_mul/int_vec.c
+++ b/samples/simple_vec_mul/int_vec.c
@@ -5,8 +5,10 @@
 #include "samples/util/util.h"
 
 // Compiled module embedded here to avoid file IO:
-#if !defined(BUILD_EMITC_STATIC)
-#include "samples/simple_vec_mul/simple_int_mul_bytecode_module_dylib_c.h"
+#if !defined(BUILD_EMITC)
+#include "iree/vm/bytecode_module.h"
+#include "samples/simple_vec_mul/simple_int_mul_bytecode_module_static.h"
+#include "samples/simple_vec_mul/simple_int_mul_bytecode_module_static_c.h"
 #else
 #include "samples/simple_vec_mul/simple_int_mul_c_module_static_c.h"
 #include "samples/simple_vec_mul/simple_int_mul_c_module_static_emitc.h"
@@ -26,17 +28,16 @@
     .model_name = "simple_int_vec_mul",
 };
 
-#if !defined(BUILD_EMITC_STATIC)
-const iree_const_byte_span_t load_bytecode_module_data() {
+iree_status_t create_module(iree_vm_module_t **module) {
+#if !defined(BUILD_EMITC)
   const struct iree_file_toc_t *module_file_toc =
-      samples_simple_vec_mul_simple_int_mul_bytecode_module_dylib_create();
-  return iree_make_const_byte_span(module_file_toc->data,
-                                   module_file_toc->size);
-}
+      samples_simple_vec_mul_simple_int_mul_bytecode_module_static_create();
+  return iree_vm_bytecode_module_create(
+      iree_make_const_byte_span(module_file_toc->data, module_file_toc->size),
+      iree_allocator_null(), iree_allocator_system(), module);
 #else
-// Function to create the C module.
-iree_status_t create_c_module(iree_vm_module_t **module) {
   return module_create(iree_allocator_system(), module);
+#endif
 }
 
 const iree_hal_executable_library_header_t **library_query(
@@ -44,7 +45,6 @@
   return simple_mul_dispatch_0_library_query(max_version,
                                              /*reserved=*/reserved);
 }
-#endif
 
 iree_status_t load_input_data(const MlModel *model, void **buffer,
                               iree_byte_span_t **byte_span) {
@@ -67,11 +67,10 @@
 }
 
 iree_status_t process_output(const MlModel *model,
-                  iree_hal_buffer_mapping_t *buffers,
-                  MlOutput *output) {
+                             iree_hal_buffer_mapping_t *buffers,
+                             MlOutput *output) {
   iree_status_t result = iree_ok_status();
-  for (int i = 0; i < buffers[0].contents.data_length / sizeof(int32_t);
-       ++i) {
+  for (int i = 0; i < buffers[0].contents.data_length / sizeof(int32_t); ++i) {
     if (((const int32_t *)buffers[0].contents.data)[i] != (i >> 1) * i) {
       result = iree_make_status(IREE_STATUS_UNKNOWN, "result mismatches");
       break;
diff --git a/samples/util/CMakeLists.txt b/samples/util/CMakeLists.txt
index 14d2170..514cbf4 100644
--- a/samples/util/CMakeLists.txt
+++ b/samples/util/CMakeLists.txt
@@ -10,34 +10,12 @@
     iree::base
     iree::hal
     iree::hal::local
-    iree::hal::local::loaders::embedded_library_loader
-    iree::hal::local::sync_driver
-    iree::modules::hal
-    iree::vm
-    iree::vm::bytecode_module
-    samples::device::device_embedded_sync
-)
-
-iree_cc_library(
-  NAME
-    util_emitc
-  HDRS
-    "util.h"
-  SRCS
-    "util.c"
-  DEPS
-    ::alloc
-    iree::base
-    iree::hal
-    iree::hal::local
     iree::hal::local::loaders::static_library_loader
     iree::hal::local::sync_driver
     iree::modules::hal
     iree::vm
     iree::vm::shims_emitc
     samples::device::device_static_loader
-  COPTS
-    "-DBUILD_EMITC_STATIC"
 )
 
 iree_cc_library(
diff --git a/samples/util/model_api.h b/samples/util/model_api.h
index a996bcb..1df0c9c 100644
--- a/samples/util/model_api.h
+++ b/samples/util/model_api.h
@@ -34,15 +34,12 @@
   uint32_t len;
 } MlOutput;
 
-// Load the VM bytecode module from the embedded c library into memory.
-const iree_const_byte_span_t load_bytecode_module_data();
-
 // Load the statically embedded library
 const iree_hal_executable_library_header_t **library_query(
     iree_hal_executable_library_version_t max_version, void *reserved);
 
-// Function to create the C module.
-iree_status_t create_c_module(iree_vm_module_t **module);
+// Function to create the bytecode or C module.
+iree_status_t create_module(iree_vm_module_t **module);
 
 // For each ML workload, based on the model configuration, allocate the buffer
 // and prepare the data. It can be loaded from a embedded image binary, a
diff --git a/samples/util/util.c b/samples/util/util.c
index f629dce..731f34e 100644
--- a/samples/util/util.c
+++ b/samples/util/util.c
@@ -14,17 +14,6 @@
 
 extern const MlModel kModel;
 
-// Function to create bytecode or C module.
-static iree_status_t create_module(iree_vm_module_t **module) {
-#if !defined(BUILD_EMITC_STATIC)
-  const iree_const_byte_span_t module_data = load_bytecode_module_data();
-  return iree_vm_bytecode_module_create(module_data, iree_allocator_null(),
-                                        iree_allocator_system(), module);
-#else
-  return create_c_module(module);
-#endif
-}
-
 // Prepare the input buffers and buffer_views based on the data type. They must
 // be released by the caller.
 static iree_status_t prepare_input_hal_buffer_views(