Compiler Guide
This guide covers installation, usage, and integration of the Fory IDL compiler.
Installation
From Source
cd compiler
pip install -e .
Verify Installation
foryc --help
Command Line Interface
Basic Usage
foryc [OPTIONS] FILES...
foryc --scan-generated [OPTIONS]
Options
Compile options:
| Option | Description | Default |
|---|---|---|
--lang | Comma-separated target languages | all |
--output, -o | Output directory | ./generated |
--package | Override package name from Fory IDL file | (from file) |
-I, --proto_path, --import_path | Add directory to import search path (can be repeated) | (none) |
--java_out=DST_DIR | Generate Java code in DST_DIR | (none) |
--python_out=DST_DIR | Generate Python code in DST_DIR | (none) |
--cpp_out=DST_DIR | Generate C++ code in DST_DIR | (none) |
--go_out=DST_DIR | Generate Go code in DST_DIR | (none) |
--rust_out=DST_DIR | Generate Rust code in DST_DIR | (none) |
--csharp_out=DST_DIR | Generate C# code in DST_DIR | (none) |
--swift_out=DST_DIR | Generate Swift code in DST_DIR | (none) |
--go_nested_type_style | Go nested type naming: camelcase or underscore | underscore |
--swift_namespace_style | Swift namespace style: enum or flatten | enum |
--emit-fdl | Emit translated FDL (for non-FDL inputs) | false |
--emit-fdl-path | Write translated FDL to this path (file or directory) | (stdout) |
For both go_nested_type_style and swift_namespace_style, schema-level file options are supported (option ... = ...;) and the CLI flag overrides the schema option when both are present.
Scan options (with --scan-generated):
| Option | Description | Default |
|---|---|---|
--root | Root directory to scan | . |
--relative | Print paths relative to root | false |
--delete | Delete matched generated files | false |
--dry-run | Scan/print only, do not delete | false |
Scan Generated Files
Use --scan-generated to find files produced by foryc. The scanner walks
the tree recursively, skips build/, target/, and hidden directories, and prints
each generated file as it is found.
# Scan current directory
foryc --scan-generated
# Scan a specific root
foryc --scan-generated --root ./src
# Print paths relative to the scan root
foryc --scan-generated --root ./src --relative
# Delete scanned generated files
foryc --scan-generated --root ./src --delete
# Dry-run (scan and print only)
foryc --scan-generated --root ./src --dry-run
Examples
Compile for all languages:
foryc schema.fdl
Compile for specific languages:
foryc schema.fdl --lang java,python,csharp,swift
Specify output directory:
foryc schema.fdl --output ./src/generated
Override package name:
foryc schema.fdl --package com.myapp.models
Compile multiple files:
foryc user.fdl order.fdl product.fdl --output ./generated
Use import search paths:
# Add a single import path
foryc src/main.fdl -I libs/common
# Add multiple import paths (repeated option)
foryc src/main.fdl -I libs/common -I libs/types
# Add multiple import paths (comma-separated)
foryc src/main.fdl -I libs/common,libs/types,third_party/
# Using --proto_path (protoc-compatible alias)
foryc src/main.fdl --proto_path=libs/common
# Mix all styles
foryc src/main.fdl -I libs/common,libs/types --proto_path third_party/
Language-specific output directories (protoc-style):
# Generate only Java code to a specific directory
foryc schema.fdl --java_out=./src/main/java
# Generate multiple languages to different directories
foryc schema.fdl --java_out=./java/gen --python_out=./python/src --go_out=./go/gen --csharp_out=./csharp/gen --swift_out=./swift/gen
# Combine with import paths
foryc schema.fdl --java_out=./gen/java -I proto/ -I common/
When using --{lang}_out options:
- Only the specified languages are generated (not all languages)
- The compiler writes under the specified directory (language-specific generators may still create package/module subdirectories)
- This is compatible with protoc-style workflows
Inspect translated Fory IDL from proto/fbs input:
# Print translated Fory IDL to stdout
foryc schema.proto --emit-fdl
# Write translated Fory IDL to a directory
foryc schema.fbs --emit-fdl --emit-fdl-path ./translated
Import Path Resolution
When compiling Fory IDL files with imports, the compiler searches for imported files in this order:
- Relative to the importing file (default) - The directory containing the file with the import statement is always searched first, automatically. No
-Iflag needed for same-directory imports. - Each
-Ipath in order - Additional search paths specified on the command line
Same-directory imports work automatically:
// main.fdl
import "common.fdl"; // Found if common.fdl is in the same directory
# No -I needed for same-directory imports
foryc main.fdl
Example project structure:
project/
├── src/
│ └── main.fdl # import "common.fdl";
└── libs/
└── common.fdl
Without -I (fails):
$ foryc src/main.fdl
Import error: Import not found: common.fdl
Searched in: /project/src
With -I (succeeds):
$ foryc src/main.fdl -I libs/
Compiling src/main.fdl...
Resolved 1 import(s)
Supported Languages
| Language | Flag | Output Extension | Description |
|---|---|---|---|
| Java | java | .java | POJOs with Fory annotations |
| Python | python | .py | Dataclasses with type hints |
| Go | go | .go | Structs with struct tags |
| Rust | rust | .rs | Structs with derive macros |
| C++ | cpp | .h | Structs with FORY macros |
| C# | csharp | .cs | Classes with Fory attributes |
| Swift | swift | .swift | @ForyObject Swift models |
Output Structure
Java
generated/
└── java/
└── com/
└── example/
├── User.java
├── Order.java
├── Status.java
└── ExampleForyRegistration.java
- One file per type (enum or message)
- Package structure matches Fory IDL package
- Registration helper class generated
Python
generated/
└── python/
└── example.py
- Single module with all types
- Module name derived from package
- Registration function included
Go
generated/
└── go/
└── example/
└── example.go
- Single file with all types
- Directory and package name are derived from
go_packageor the Fory IDL package - Registration function included
Rust
generated/
└── rust/
└── example.rs
- Single module with all types
- Module name derived from package
- Registration function included
C++
generated/
└── cpp/
└── example.h
- Single header file
- Namespace matches package (dots to
::) - Header guards and forward declarations
C#
generated/
└── csharp/
└── example/
└── example.cs
- Single
.csfile per schema - Namespace uses
csharp_namespace(if set) or Fory IDL package - Includes registration helper and
ToBytes/FromBytesmethods - Imported schemas are registered transitively (for example
root.idlimportingaddressbook.fdlandtree.fdl)
Swift
generated/
└── swift/
└── addressbook/
└── addressbook.swift
- Single
.swiftfile per schema - Package segments are mapped to nested Swift enums (for example
addressbook.*->Addressbook.*) - Generated messages/unions/enums use
@ForyObjectand@ForyField(id: ...) - Union types are generated as tagged enums with associated payload values
- Each schema includes
ForyRegistrationandtoBytes/fromByteshelpers - Imported schemas are registered transitively by generated registration helpers
C# IDL Matrix Verification
Run the end-to-end C# IDL matrix (FDL/IDL/Proto/FBS generation plus roundtrip tests):
cd integration_tests/idl_tests
./run_csharp_tests.sh
This runner executes schema-consistent and compatible roundtrips across:
addressbook,auto_id,complex_pbprimitivescollectionand union/list variantsoptional_typesany_example(.fdl) andany_example(.proto)treeandgraphreference-tracking casesmonster.fbsandcomplex_fbs.fbsroot.idlcross-package import coverage- evolving schema compatibility cases
Swift IDL Matrix Verification
Run the end-to-end Swift IDL matrix (FDL/IDL/Proto/FBS generation plus roundtrip tests):
cd integration_tests/idl_tests
./run_swift_tests.sh
This runs:
- local Swift IDL roundtrip tests in both compatible and schema-consistent modes
- Java-driven peer roundtrip validation with
IDL_PEER_LANG=swift
The script also sets DATA_FILE* variables so file-based roundtrip paths are exercised.