Add c_embed_data build tool (#5540) Add the build tool to generate c embed data for testing. The code is used to bypass fileIO and it can be used with the C API. Change the build rule of iree_bytecode_module to include the c embed codegen. The user needs to assign a non-empty value in the "c_output" field. build_tools/embed_data/generate_embed_data_main.cc now can produce either c code or c++ code, controlled by --c_output flag.
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9958c07..92f7dfe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -218,6 +218,7 @@ include(iree_tablegen_library) include(iree_tablegen_doc) include(iree_cc_embed_data) +include(iree_c_embed_data) include(iree_bytecode_module) include(iree_c_module) include(iree_python)
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py index 72ce425..5d86fae 100644 --- a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py +++ b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py
@@ -447,6 +447,37 @@ f"{flatten_block}" f" PUBLIC\n)\n\n") + def c_embed_data(self, + name, + srcs, + c_file_output, + h_file_output, + testonly=None, + strip_prefix=None, + flatten=None, + identifier=None, + **kwargs): + if identifier: + self._convert_unimplemented_function("c_embed_data", + name + " has identifier") + name_block = _convert_string_arg_block("NAME", name, quote=False) + srcs_block = _convert_srcs_block(srcs) + c_file_output_block = _convert_string_arg_block("C_FILE_OUTPUT", + c_file_output) + h_file_output_block = _convert_string_arg_block("H_FILE_OUTPUT", + h_file_output) + testonly_block = _convert_option_block("TESTONLY", testonly) + flatten_block = _convert_option_block("FLATTEN", flatten) + + self.converter.body += (f"iree_c_embed_data(\n" + f"{name_block}" + f"{srcs_block}" + f"{c_file_output_block}" + f"{h_file_output_block}" + f"{testonly_block}" + f"{flatten_block}" + f" PUBLIC\n)\n\n") + def spirv_kernel_cc_library(self, name, srcs): name_block = _convert_string_arg_block("NAME", name, quote=False) srcs_block = _convert_srcs_block(srcs) @@ -462,10 +493,12 @@ flags=None, translate_tool=None, cc_namespace=None, + c_output=None, testonly=None): name_block = _convert_string_arg_block("NAME", name, quote=False) src_block = _convert_string_arg_block("SRC", src) namespace_block = _convert_string_arg_block("CC_NAMESPACE", cc_namespace) + c_output_block = _convert_option_block("C_OUTPUT", c_output) translate_tool_block = _convert_translate_tool_block(translate_tool) flags_block = _convert_string_list_block("FLAGS", flags) testonly_block = _convert_option_block("TESTONLY", testonly) @@ -474,6 +507,7 @@ f"{name_block}" f"{src_block}" f"{namespace_block}" + f"{c_output_block}" f"{translate_tool_block}" f"{flags_block}" f"{testonly_block}"
diff --git a/build_tools/cmake/iree_bytecode_module.cmake b/build_tools/cmake/iree_bytecode_module.cmake index 0af567a..e297083 100644 --- a/build_tools/cmake/iree_bytecode_module.cmake +++ b/build_tools/cmake/iree_bytecode_module.cmake
@@ -26,6 +26,7 @@ # TRANSLATE_TOOL: Translation tool to invoke (CMake target). The default # tool is "iree-translate". # CC_NAMESPACE: Wraps everything in a C++ namespace. +# C_OUTPUT: Control flag to generate c embed code instead. # PUBLIC: Add this so that this library will be exported under ${PACKAGE}:: # Also in IDE, target will appear in ${PACKAGE} folder while non PUBLIC # will be in ${PACKAGE}/internal. @@ -39,7 +40,7 @@ function(iree_bytecode_module) cmake_parse_arguments( _RULE - "PUBLIC;TESTONLY" + "PUBLIC;TESTONLY;C_OUTPUT" "NAME;SRC;TRANSLATE_TOOL;CC_NAMESPACE" "FLAGS" ${ARGN} @@ -104,4 +105,22 @@ "${_TESTONLY_ARG}" ) endif() + + if(_RULE_C_OUTPUT) + iree_c_embed_data( + NAME + "${_RULE_NAME}_c" + IDENTIFIER + "${_RULE_NAME}_c" + GENERATED_SRCS + "${_RULE_NAME}.vmfb" + C_FILE_OUTPUT + "${_RULE_NAME}_c.c" + H_FILE_OUTPUT + "${_RULE_NAME}_c.h" + FLATTEN + "${_PUBLIC_ARG}" + "${_TESTONLY_ARG}" + ) + endif() endfunction()
diff --git a/build_tools/cmake/iree_c_embed_data.cmake b/build_tools/cmake/iree_c_embed_data.cmake new file mode 100644 index 0000000..0037daf --- /dev/null +++ b/build_tools/cmake/iree_c_embed_data.cmake
@@ -0,0 +1,97 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://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. + +include(CMakeParseArguments) + +# iree_c_embed_data() +# +# CMake function to imitate Bazel's c_embed_data rule. +# +# Parameters: +# NAME: Name of target (see Note). +# SRCS: List of source files to embed. +# GENERATED_SRCS: List of generated source files to embed. +# C_FILE_OUTPUT: The C implementation file to output. +# H_FILE_OUTPUT: The H header file to output. +# STRIP_PREFIX: Strips this verbatim prefix from filenames (in the TOC). +# FLATTEN: Removes all directory components from filenames (in the TOC). +# IDENTIFIER: The identifier to use in generated names (defaults to name). +# PUBLIC: Add this so that this library will be exported under ${PACKAGE}:: +# Also in IDE, target will appear in ${PACKAGE} folder while non PUBLIC will be +# in ${PACKAGE}/internal. +# TESTONLY: When added, this target will only be built if user passes +# -DIREE_BUILD_TESTS=ON to CMake. +# TODO(scotttodd): Support passing KWARGS down into iree_cc_library? +# +function(iree_c_embed_data) + cmake_parse_arguments( + _RULE + "PUBLIC;TESTONLY;FLATTEN" + "NAME;IDENTIFIER;STRIP_PREFIX;C_FILE_OUTPUT;H_FILE_OUTPUT" + "SRCS;GENERATED_SRCS" + ${ARGN} + ) + + if(_RULE_TESTONLY AND NOT IREE_BUILD_TESTS) + return() + endif() + + if(DEFINED _RULE_IDENTIFIER) + set(_IDENTIFIER ${_RULE_IDENTIFIER}) + else() + set(_IDENTIFIER ${_RULE_NAME}) + endif() + + set(_ARGS) + list(APPEND _ARGS "--output_header=${_RULE_H_FILE_OUTPUT}") + list(APPEND _ARGS "--output_impl=${_RULE_C_FILE_OUTPUT}") + list(APPEND _ARGS "--identifier=${_IDENTIFIER}") + list(APPEND _ARGS "--c_output=true") + if(DEFINED _RULE_STRIP_PREFIX}) + list(APPEND _ARGS "--strip_prefix=${_RULE_STRIP_PREFIX}") + endif() + if(DEFINED _RULE_FLATTEN}) + list(APPEND _ARGS "--flatten") + endif() + + foreach(SRC ${_RULE_SRCS}) + list(APPEND _ARGS "${CMAKE_CURRENT_SOURCE_DIR}/${SRC}") + endforeach(SRC) + foreach(SRC ${_RULE_GENERATED_SRCS}) + list(APPEND _ARGS "${SRC}") + endforeach(SRC) + + iree_get_executable_path(_EXE_PATH generate_embed_data) + + add_custom_command( + OUTPUT "${_RULE_H_FILE_OUTPUT}" "${_RULE_C_FILE_OUTPUT}" + COMMAND ${_EXE_PATH} ${_ARGS} + DEPENDS ${_EXE_PATH} ${_RULE_SRCS} ${_RULE_GENERATED_SRCS} + ) + + if(_RULE_TESTONLY) + set(_TESTONLY_ARG "TESTONLY") + endif() + if(_RULE_PUBLIC) + set(_PUBLIC_ARG "PUBLIC") + endif() + + iree_cc_library( + NAME ${_RULE_NAME} + HDRS "${_RULE_H_FILE_OUTPUT}" + SRCS "${_RULE_C_FILE_OUTPUT}" + "${_PUBLIC_ARG}" + "${_TESTONLY_ARG}" + ) +endfunction()
diff --git a/build_tools/cmake/iree_cc_embed_data.cmake b/build_tools/cmake/iree_cc_embed_data.cmake index 7eeac23..893c2e9 100644 --- a/build_tools/cmake/iree_cc_embed_data.cmake +++ b/build_tools/cmake/iree_cc_embed_data.cmake
@@ -62,6 +62,7 @@ list(APPEND _ARGS "--output_header=${_RULE_H_FILE_OUTPUT}") list(APPEND _ARGS "--output_impl=${_RULE_CC_FILE_OUTPUT}") list(APPEND _ARGS "--identifier=${_IDENTIFIER}") + list(APPEND _ARGS "--c_output=false") if(DEFINED _RULE_CPP_NAMESPACE) list(APPEND _ARGS "--cpp_namespace=${_RULE_CPP_NAMESPACE}") endif() @@ -79,7 +80,7 @@ list(APPEND _ARGS "${SRC}") endforeach(SRC) - iree_get_executable_path(_EXE_PATH generate_cc_embed_data) + iree_get_executable_path(_EXE_PATH generate_embed_data) add_custom_command( OUTPUT "${_RULE_H_FILE_OUTPUT}" "${_RULE_CC_FILE_OUTPUT}"
diff --git a/build_tools/embed_data/BUILD b/build_tools/embed_data/BUILD index 37097f6..0ade681 100644 --- a/build_tools/embed_data/BUILD +++ b/build_tools/embed_data/BUILD
@@ -14,7 +14,7 @@ # Generates source files with embedded file contents. -load(":build_defs.bzl", "cc_embed_data") +load(":build_defs.bzl", "c_embed_data", "cc_embed_data") package( default_visibility = ["//visibility:public"], @@ -23,8 +23,8 @@ ) cc_binary( - name = "generate_cc_embed_data", - srcs = ["generate_cc_embed_data_main.cc"], + name = "generate_embed_data", + srcs = ["generate_embed_data_main.cc"], deps = [ "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", @@ -66,3 +66,25 @@ "//iree/testing:gtest_main", ], ) + +c_embed_data( + name = "testembed1_c", + # do not sort + srcs = [ + "file1.txt", + "data/file2.txt", + ], + c_file_output = "testembed1_c.c", + flatten = True, + h_file_output = "testembed1_c.h", +) + +cc_test( + name = "c_embed_data_test", + srcs = ["c_embed_data_test.cc"], + deps = [ + ":testembed1_c", + "//iree/testing:gtest", + "//iree/testing:gtest_main", + ], +)
diff --git a/build_tools/embed_data/CMakeLists.txt b/build_tools/embed_data/CMakeLists.txt index 7f28f75..92ac014 100644 --- a/build_tools/embed_data/CMakeLists.txt +++ b/build_tools/embed_data/CMakeLists.txt
@@ -13,16 +13,17 @@ # limitations under the License. if(NOT CMAKE_CROSSCOMPILING) - add_executable(generate_cc_embed_data) - target_sources(generate_cc_embed_data PRIVATE generate_cc_embed_data_main.cc) - set_target_properties(generate_cc_embed_data PROPERTIES OUTPUT_NAME generate_cc_embed_data) + add_executable(generate_embed_data) + target_sources(generate_embed_data PRIVATE generate_embed_data_main.cc) + set_target_properties(generate_embed_data PROPERTIES OUTPUT_NAME generate_embed_data) - target_link_libraries(generate_cc_embed_data + target_link_libraries(generate_embed_data absl::flags absl::flags_parse absl::strings ) - install(TARGETS generate_cc_embed_data - COMPONENT generate_cc_embed_data + + install(TARGETS generate_embed_data + COMPONENT generate_embed_data RUNTIME DESTINATION bin) endif()
diff --git a/build_tools/embed_data/build_defs.bzl b/build_tools/embed_data/build_defs.bzl index 872542a..bb16601 100644 --- a/build_tools/embed_data/build_defs.bzl +++ b/build_tools/embed_data/build_defs.bzl
@@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Embeds data files into a C++ module.""" +"""Embeds data files into a C or C++ module.""" def cc_embed_data( name, @@ -57,7 +57,7 @@ identifier: The identifier to use in generated names (defaults to name). **kwargs: Args to pass to the cc_library. """ - generator = "//build_tools/embed_data:generate_cc_embed_data" + generator = "//build_tools/embed_data:generate_embed_data" generator_location = "$(location %s)" % generator if identifier == None: identifier = name @@ -66,6 +66,7 @@ cc_file_output, ) flags += " --identifier='%s'" % (identifier,) + flags += " --c_output=false" if cpp_namespace != None: flags += " --cpp_namespace='%s'" % (cpp_namespace,) if strip_prefix != None: @@ -91,3 +92,87 @@ testonly = testonly, **kwargs ) + +def c_embed_data( + name, + srcs, + c_file_output, + h_file_output, + testonly = False, + strip_prefix = None, + flatten = False, + identifier = None, + **kwargs): + """Embeds 'srcs' into a C module. + + Generates a header like: + #if __cplusplus + extern "C" { + #endif // __cplusplus + struct FileToc { + const char* name; // the file's original name + const char* data; // beginning of the file + size_t size; // length of the file + }; + #if __cplusplus + } + #endif // __cplusplus + + #if __cplusplus + extern "C" { + #endif // __cplusplus + const struct FileToc* this_rule_name__create(); + #if __cplusplus + } + #endif // __cplusplus + + The 'this_rule_name()' function will return an array of FileToc + structs terminated by one that has NULL 'name' and 'data' fields. + The 'data' field always has an extra null terminator at the end (which + is not included in the size). + + Args: + name: The rule name, which will also be the identifier of the generated + code symbol. + srcs: List of files to embed. + c_file_output: The C implementation file to output. + h_file_output: The H header file to output. + testonly: If True, only testonly targets can depend on this target. + strip_prefix: Strips this verbatim prefix from filenames (in the TOC). + flatten: Removes all directory components from filenames (in the TOC). + identifier: The identifier to use in generated names (defaults to name). + **kwargs: Args to pass to the cc_library. + """ + generator = "//build_tools/embed_data:generate_embed_data" + generator_location = "$(location %s)" % generator + if identifier == None: + identifier = name + flags = "--output_header='$(location %s)' --output_impl='$(location %s)'" % ( + h_file_output, + c_file_output, + ) + flags += " --c_output=true" + flags += " --identifier='%s'" % (identifier,) + if strip_prefix != None: + flags += " --strip_prefix='%s'" % (strip_prefix,) + if flatten: + flags += " --flatten" + + native.genrule( + name = name + "__generator", + srcs = srcs, + outs = [ + c_file_output, + h_file_output, + ], + tools = [generator], + cmd = "%s $(SRCS) %s" % (generator_location, flags), + testonly = testonly, + ) + native.cc_library( + name = name, + hdrs = [h_file_output], + srcs = [c_file_output], + testonly = testonly, + **kwargs + )
diff --git a/build_tools/embed_data/c_embed_data_test.cc b/build_tools/embed_data/c_embed_data_test.cc new file mode 100644 index 0000000..a112907 --- /dev/null +++ b/build_tools/embed_data/c_embed_data_test.cc
@@ -0,0 +1,42 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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. + +#include "build_tools/embed_data/testembed1_c.h" +#include "iree/testing/gtest.h" + +namespace { + +TEST(Generator, TestContents) { + auto* toc1 = testembed1_c_create(); + ASSERT_EQ("file1.txt", std::string(toc1->name)); + ASSERT_EQ(R"(Are you '"Still"' here?)" + "\n", + std::string(toc1->data)); + ASSERT_EQ(24, toc1->size); + ASSERT_EQ(0, *(toc1->data + toc1->size)); + + ++toc1; + ASSERT_EQ("file2.txt", std::string(toc1->name)); + ASSERT_EQ(R"(¯\_(ツ)_/¯)" + "\n", + std::string(toc1->data)); + ASSERT_EQ(14, toc1->size); + ASSERT_EQ(0, *(toc1->data + toc1->size)); + + ++toc1; + ASSERT_EQ(nullptr, toc1->name); + ASSERT_EQ(nullptr, toc1->data); +} + +} // namespace
diff --git a/build_tools/embed_data/generate_cc_embed_data_main.cc b/build_tools/embed_data/generate_embed_data_main.cc similarity index 68% rename from build_tools/embed_data/generate_cc_embed_data_main.cc rename to build_tools/embed_data/generate_embed_data_main.cc index 0ded0e6..137479c 100644 --- a/build_tools/embed_data/generate_cc_embed_data_main.cc +++ b/build_tools/embed_data/generate_embed_data_main.cc
@@ -25,12 +25,25 @@ ABSL_FLAG(std::string, identifier, "resources", "name of the resources function"); ABSL_FLAG(std::string, output_header, "", "output header file"); -ABSL_FLAG(std::string, output_impl, "", "output cc impl file"); +ABSL_FLAG(std::string, output_impl, "", "output impl file"); ABSL_FLAG(std::string, cpp_namespace, "", "generate in a c++ namespace"); +ABSL_FLAG(bool, c_output, false, "generate a c output"); ABSL_FLAG(std::string, strip_prefix, "", "strip prefix from filenames"); ABSL_FLAG(bool, flatten, false, "whether to flatten the directory structure (only include basename)"); +void GenerateExternCOpen(std::ofstream& f) { + f << "\n#if __cplusplus\n"; + f << "extern \"C\" {\n"; + f << "#endif // __cplusplus\n"; +} + +void GenerateExternCClose(std::ofstream& f) { + f << "#if __cplusplus\n"; + f << "}\n"; + f << "#endif // __cplusplus\n\n"; +} + void GenerateNamespaceOpen(std::ofstream& f) { const auto& ns = absl::GetFlag(FLAGS_cpp_namespace); if (ns.empty()) return; @@ -54,32 +67,58 @@ } void GenerateTocStruct(std::ofstream& f) { + const auto& c_output = absl::GetFlag(FLAGS_c_output); f << "#ifndef IREE_FILE_TOC\n"; f << "#define IREE_FILE_TOC\n"; - f << "namespace iree {\n"; + if (c_output) { + GenerateExternCOpen(f); + } else { + f << "namespace iree {\n"; + } f << "struct FileToc {\n"; f << " const char* name; // the file's original name\n"; f << " const char* data; // beginning of the file\n"; - f << " std::size_t size; // length of the file\n"; - f << "};\n"; - f << "} // namespace iree\n"; + if (c_output) { + f << " size_t size; // length of the file\n"; + f << "};\n"; + GenerateExternCClose(f); + } else { + f << " std::size_t size; // length of the file\n"; + f << "};\n"; + f << "} // namespace iree\n"; + } f << "#endif // IREE_FILE_TOC\n"; } bool GenerateHeader(const std::string& header_file, const std::vector<std::string>& toc_files) { std::ofstream f(header_file, std::ios::out | std::ios::trunc); + const auto& c_output = absl::GetFlag(FLAGS_c_output); + f << "#pragma once\n"; // Pragma once isn't great but is the best we can do. - f << "#include <cstddef>\n"; - GenerateTocStruct(f); - GenerateNamespaceOpen(f); - f << "extern const struct ::iree::FileToc* " - << absl::GetFlag(FLAGS_identifier) << "_create();\n"; - f << "static inline std::size_t " << absl::GetFlag(FLAGS_identifier) - << "_size() { \n"; - f << " return " << toc_files.size() << ";\n"; - f << "}\n"; - GenerateNamespaceClose(f); + if (c_output) { + f << "#include <stddef.h>\n"; + GenerateTocStruct(f); + GenerateExternCOpen(f); + f << "const struct FileToc* " << absl::GetFlag(FLAGS_identifier) + << "_create();\n"; + f << "static inline size_t " << absl::GetFlag(FLAGS_identifier) + << "_size() {\n"; + f << " return " << toc_files.size() << ";\n"; + f << "}\n"; + GenerateExternCClose(f); + } else { + f << "#include <cstddef>\n"; + GenerateTocStruct(f); + GenerateNamespaceOpen(f); + f << "extern const struct ::iree::FileToc* " + << absl::GetFlag(FLAGS_identifier) << "_create();\n"; + f << "static inline std::size_t " << absl::GetFlag(FLAGS_identifier) + << "_size() { \n"; + f << " return " << toc_files.size() << ";\n"; + f << "}\n"; + GenerateNamespaceClose(f); + } f.close(); return f.good(); } @@ -109,9 +148,16 @@ const std::vector<std::string>& input_files, const std::vector<std::string>& toc_files) { std::ofstream f(impl_file, std::ios::out | std::ios::trunc); - f << "#include <cstddef>\n"; - GenerateTocStruct(f); - GenerateNamespaceOpen(f); + const auto& c_output = absl::GetFlag(FLAGS_c_output); + if (c_output) { + f << "#include <stddef.h>\n"; + f << "#include <stdalign.h>\n"; + GenerateTocStruct(f); + } else { + f << "#include <cstddef>\n"; + GenerateTocStruct(f); + GenerateNamespaceOpen(f); + } for (size_t i = 0, e = input_files.size(); i < e; ++i) { f << "alignas(alignof(void*)) static char const file_" << i << "[] = {\n"; std::string contents; @@ -128,7 +174,11 @@ } f << "};\n"; } - f << "static const struct ::iree::FileToc toc[] = {\n"; + if (c_output) { + f << "static const struct FileToc toc[] = {\n"; + } else { + f << "static const struct ::iree::FileToc toc[] = {\n"; + } assert(input_files.size() == toc_files.size()); for (size_t i = 0, e = input_files.size(); i < e; ++i) { f << " {\n"; @@ -137,14 +187,22 @@ f << " sizeof(file_" << i << ") - 1\n"; f << " },\n"; } - f << " {nullptr, nullptr, 0},\n"; - f << "};\n"; - f << "const struct ::iree::FileToc* " << absl::GetFlag(FLAGS_identifier) - << "_create() {\n"; + if (c_output) { + f << " {NULL, NULL, 0},\n"; + f << "};\n"; + f << "const struct FileToc* " << absl::GetFlag(FLAGS_identifier) + << "_create() {\n"; + } else { + f << " {nullptr, nullptr, 0},\n"; + f << "};\n"; + f << "const struct ::iree::FileToc* " << absl::GetFlag(FLAGS_identifier) + << "_create() {\n"; + } f << " return &toc[0];\n"; f << "}\n"; - - GenerateNamespaceClose(f); + if (!c_output) { + GenerateNamespaceClose(f); + } f.close(); return f.good(); } @@ -175,7 +233,12 @@ } toc_files.push_back(toc_file); } - + // Can either generate the c or c++ output. + if (!absl::GetFlag(FLAGS_cpp_namespace).empty() && + absl::GetFlag(FLAGS_c_output)) { + std::cerr << "Can only generate either c or c++ output.\n"; + return 1; + } if (!absl::GetFlag(FLAGS_output_header).empty()) { if (!GenerateHeader(absl::GetFlag(FLAGS_output_header), toc_files)) { std::cerr << "Error generating headers.\n";
diff --git a/iree/tools/compilation.bzl b/iree/tools/compilation.bzl index b3a85be..159df41 100644 --- a/iree/tools/compilation.bzl +++ b/iree/tools/compilation.bzl
@@ -14,7 +14,7 @@ """Rules for compiling IREE executables, modules, and archives.""" -load("//build_tools/embed_data:build_defs.bzl", "cc_embed_data") +load("//build_tools/embed_data:build_defs.bzl", "c_embed_data", "cc_embed_data") # TODO(benvanik): port to a full starlark rule, document, etc. def iree_bytecode_module( @@ -23,6 +23,7 @@ flags = ["-iree-mlir-to-vm-bytecode-module"], translate_tool = "//iree/tools:iree-translate", cc_namespace = None, + c_output = False, **kwargs): native.genrule( name = name, @@ -57,3 +58,14 @@ flatten = True, **kwargs ) + # Embed the module for use in C. + if c_output: + c_embed_data( + name = "%s_c" % (name), + identifier = "%s_c" % (name), + srcs = ["%s.vmfb" % (name)], + c_file_output = "%s_c.c" % (name), + h_file_output = "%s_c.h" % (name), + flatten = True, + **kwargs + )