Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ exclude =
./build,
./configurations,
./docs,
./exir/_serialize/generated/executorch_flatbuffer,
./third_party,
*.pyi

Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/validate_flatbuffer_gen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Validate Flatbuffer Generation

on:
workflow_dispatch:
pull_request:
paths:
- "schema/**"
- "exir/_serialize/generated/executorch_flatbuffer/**"

jobs:
exir-flatbuffer:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: setup python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: install executorch (with flatc)
run: ./install_executorch.sh -e

- name: Generate flatbuffer Python
run: python exir/_serialize/generate_program.py

- name: Validate executorch_flatbuffer is unchanged
run: |
git add -A exir/_serialize/generated/executorch_flatbuffer
if ! git diff --cached --quiet -- exir/_serialize/generated/executorch_flatbuffer; then
echo "Error: executorch_flatbuffer has uncommitted changes."
echo "Please run 'python exir/_serialize/generate_program.py' to regenerate the files and commit the changes."
exit 1
fi
2 changes: 2 additions & 0 deletions .lintrunner.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exclude_patterns = [
'**/third-party/**',
'.github/scripts/**',
'exir/serde/**',
'exir/_serialize/generated/executorch_flatbuffer/**',
]
command = [
'python',
Expand Down Expand Up @@ -39,6 +40,7 @@ exclude_patterns = [
'third-party/**',
'**/third-party/**',
'exir/serde/**',
'exir/_serialize/generated/executorch_flatbuffer/**',
]
command = [
'python',
Expand Down
4 changes: 3 additions & 1 deletion exir/_serialize/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ fbcode_target(_kind = runtime.python_library,
"_cord.py",
"_dataclass.py",
"_flatbuffer.py",
"_flatbuffer_program.py",
"_named_data_store.py",
"_program.py",
"_serialize.py",
"data_serializer.py",
"padding.py",
],
] + glob(["generated/**/*.py"]),
resources = {
"//executorch/schema:program.fbs": "program.fbs",
"//executorch/schema:scalar_type.fbs": "scalar_type.fbs",
Expand All @@ -47,6 +48,7 @@ fbcode_target(_kind = runtime.python_library,
# Please ask before changing this.
visibility = ["PUBLIC"],
deps = [
"fbsource//third-party/pypi/flatbuffers:flatbuffers",
"//executorch/exir:schema",
"//executorch/exir:tensor",
"//executorch/exir:tensor_layout",
Expand Down
59 changes: 59 additions & 0 deletions exir/_serialize/_flatbuffer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
Expand Down Expand Up @@ -94,6 +95,28 @@ def __call__(self, schema: bytes) -> bytes:
return schema


class _SchemaFileIdentifierGetter:
"""Finds the file_identifier value in flatbuffer schemas."""

def __init__(self) -> None:
self.file_identifier: Optional[bytes] = None

def __call__(self, schema: bytes) -> bytes:
identifiers = re.findall(rb'file_identifier\s+"([^"]+)"', schema)
for file_identifier in identifiers:
if len(file_identifier) != 4:
raise ValueError(
f"Invalid file_identifier length {len(file_identifier)} in schema"
)
if self.file_identifier is None:
self.file_identifier = file_identifier
elif self.file_identifier != file_identifier:
raise ValueError(
f"Mismatched file_identifier {file_identifier} != {self.file_identifier}"
)
return schema


class _ResourceFiles:
"""Manages a collection of python resources that will be written to files."""

Expand All @@ -112,6 +135,10 @@ def patch_files(self, patch_fn: Callable[[bytes], bytes]) -> None:
for name in self._files.keys():
self._files[name] = patch_fn(self._files[name])

def get(self, name: str) -> bytes:
"""Returns the current contents of the named file."""
return self._files[name]

def write_to(self, out_dir: str) -> None:
"""Writes the files to the specified directory. File names are based on
the original resource names.
Expand All @@ -131,6 +158,15 @@ class _SchemaInfo:
# schema files.
max_alignment: int

# The file identifier declared in the root schema.
file_identifier: bytes

# The alignment for constant tensor data in the schema.
tensor_alignment: int

# The alignment for delegate data in the schema.
delegate_alignment: int


def _prepare_schema(
out_dir: str,
Expand Down Expand Up @@ -158,13 +194,36 @@ def _prepare_schema(
# Find the largest alignment used in the patched schema files.
get_alignments = _SchemaMaxAlignmentGetter()
schemas.patch_files(get_alignments)
get_file_identifier = _SchemaFileIdentifierGetter()
schemas.patch_files(get_file_identifier)
if get_file_identifier.file_identifier is None:
raise ValueError("Missing file_identifier in schema files.")

def extract_alignment(schema: bytes, marker: bytes) -> int:
for line in schema.splitlines():
if marker in line:
match = re.search(rb"force_align\s*:\s*(\d+)", line)
if match:
return int(match.group(1))
Comment thread
JacobSzwejbka marked this conversation as resolved.
raise RuntimeError(f"Failed to find marker {marker!r} in program.fbs")
Comment thread
chizkiyahu marked this conversation as resolved.

program_schema_data = schemas.get(program_schema)
tensor_alignment = extract_alignment(
program_schema_data, b"@executorch-tensor-alignment"
)
effective_delegate_alignment = extract_alignment(
program_schema_data, b"@executorch-delegate-alignment"
)

# Write the patched schema files to the filesystem.
schemas.write_to(out_dir)

return _SchemaInfo(
root_path=os.path.join(out_dir, program_schema),
max_alignment=get_alignments.max_alignment,
file_identifier=get_file_identifier.file_identifier,
tensor_alignment=tensor_alignment,
delegate_alignment=effective_delegate_alignment,
)


Expand Down
Loading
Loading