title: Compiler Guide sidebar_position: 3 id: compiler_guide license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You 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
http://www.apache.org/licenses/LICENSE-2.0
This guide covers installation, usage, and integration of the FDL compiler.
cd compiler pip install -e .
fory compile --help
fory compile [OPTIONS] FILES...
| Option | Description | Default |
|---|---|---|
--lang | Comma-separated target languages | all |
--output, -o | Output directory | ./generated |
--package | Override package name from FDL 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) |
--go_nested_type_style | Go nested type naming: camelcase or underscore | (none) |
Compile for all languages:
fory compile schema.fdl
Compile for specific languages:
fory compile schema.fdl --lang java,python
Specify output directory:
fory compile schema.fdl --output ./src/generated
Override package name:
fory compile schema.fdl --package com.myapp.models
Compile multiple files:
fory compile user.fdl order.fdl product.fdl --output ./generated
Use import search paths:
# Add a single import path fory compile src/main.fdl -I libs/common # Add multiple import paths (repeated option) fory compile src/main.fdl -I libs/common -I libs/types # Add multiple import paths (comma-separated) fory compile src/main.fdl -I libs/common,libs/types,third_party/ # Using --proto_path (protoc-compatible alias) fory compile src/main.fdl --proto_path=libs/common # Mix all styles fory compile 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 fory compile schema.fdl --java_out=./src/main/java # Generate multiple languages to different directories fory compile schema.fdl --java_out=./java/gen --python_out=./python/src --go_out=./go/gen # Combine with import paths fory compile schema.fdl --java_out=./gen/java -I proto/ -I common/
When using --{lang}_out options:
{lang}/ subdirectory)When compiling FDL files with imports, the compiler searches for imported files in this order:
-I flag needed for same-directory imports.-I path in order - Additional search paths specified on the command lineSame-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 fory compile main.fdl
Example project structure:
project/
├── src/
│ └── main.fdl # import "common.fdl";
└── libs/
└── common.fdl
Without -I (fails):
$ fory compile src/main.fdl Import error: Import not found: common.fdl Searched in: /project/src
With -I (succeeds):
$ fory compile src/main.fdl -I libs/ Compiling src/main.fdl... Resolved 1 import(s)
| 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 |
generated/
└── java/
└── com/
└── example/
├── User.java
├── Order.java
├── Status.java
└── ExampleForyRegistration.java
generated/
└── python/
└── example.py
generated/
└── go/
└── example.go
generated/
└── rust/
└── example.rs
generated/
└── cpp/
└── example.h
::)Add to your pom.xml:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>generate-fory-types</id> <phase>generate-sources</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>fory</executable> <arguments> <argument>compile</argument> <argument>${project.basedir}/src/main/fdl/schema.fdl</argument> <argument>--lang</argument> <argument>java</argument> <argument>--output</argument> <argument>${project.build.directory}/generated-sources/fdl</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build>
Add generated sources:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.4.0</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${project.build.directory}/generated-sources/fdl</source> </sources> </configuration> </execution> </executions> </plugin> </plugins> </build>
Add to build.gradle:
task generateForyTypes(type: Exec) { commandLine 'fory', 'compile', "${projectDir}/src/main/fdl/schema.fdl", '--lang', 'java', '--output', "${buildDir}/generated/sources/fdl" } compileJava.dependsOn generateForyTypes sourceSets { main { java { srcDir "${buildDir}/generated/sources/fdl/java" } } }
Add to setup.py or pyproject.toml:
# setup.py from setuptools import setup from setuptools.command.build_py import build_py import subprocess class BuildWithFdl(build_py): def run(self): subprocess.run([ 'fory', 'compile', 'schema.fdl', '--lang', 'python', '--output', 'src/generated' ], check=True) super().run() setup( cmdclass={'build_py': BuildWithFdl}, # ... )
Add to your Go file:
//go:generate fory compile ../schema.fdl --lang go --output . package models
Run:
go generate ./...
Add to build.rs:
use std::process::Command; fn main() { println!("cargo:rerun-if-changed=schema.fdl"); let status = Command::new("fory") .args(&["compile", "schema.fdl", "--lang", "rust", "--output", "src/generated"]) .status() .expect("Failed to run fory compiler"); if !status.success() { panic!("FDL compilation failed"); } }
Add to CMakeLists.txt:
find_program(FORY_COMPILER fory) add_custom_command( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/generated/example.h COMMAND ${FORY_COMPILER} compile ${CMAKE_CURRENT_SOURCE_DIR}/schema.fdl --lang cpp --output ${CMAKE_CURRENT_SOURCE_DIR}/generated DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/schema.fdl COMMENT "Generating FDL types" ) add_custom_target(generate_fdl DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/generated/example.h) add_library(mylib ...) add_dependencies(mylib generate_fdl) target_include_directories(mylib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated)
Create a rule in BUILD:
genrule( name = "generate_fdl", srcs = ["schema.fdl"], outs = ["generated/example.h"], cmd = "$(location //:fory_compiler) compile $(SRCS) --lang cpp --output $(RULEDIR)/generated", tools = ["//:fory_compiler"], ) cc_library( name = "models", hdrs = [":generate_fdl"], # ... )
Error: Line 5, Column 12: Expected ';' after field declaration
Fix: Check the indicated line for missing semicolons or syntax issues.
Error: Duplicate type name: User
Fix: Ensure each enum and message has a unique name within the file.
Error: Duplicate type ID 100: User and Order
Fix: Assign unique type IDs to each type.
Error: Unknown type 'Address' in Customer.address
Fix: Define the referenced type before using it, or check for typos.
Error: Duplicate field number 1 in User: name and id
Fix: Assign unique field numbers within each message.
project/ ├── fdl/ │ ├── common.fdl # Shared types │ ├── user.fdl # User domain │ └── order.fdl # Order domain ├── src/ │ └── generated/ # Generated code (git-ignored) └── build.gradle
Add to .gitignore:
# Generated FDL code src/generated/ generated/
Always regenerate during builds:
# GitHub Actions example steps: - name: Install FDL Compiler run: pip install ./compiler - name: Generate Types run: fory compile fdl/*.fdl --output src/generated - name: Build run: ./gradlew build
When modifying schemas:
optional - For backward compatibilitymessage User [id=100] { string id = 1; string name = 2; // Field 3 was removed, don't reuse optional string email = 4; // New field }
fory: command not found
Solution: Ensure the compiler is installed and in your PATH:
pip install -e ./compiler # Or add to PATH export PATH=$PATH:~/.local/bin
Permission denied: ./generated
Solution: Ensure write permissions on the output directory:
chmod -R u+w ./generated
Java: Ensure Fory dependency is in your project:
<dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-core</artifactId> <version>0.14.1</version> </dependency>
Python: Ensure pyfory is installed:
pip install pyfory
Go: Ensure fory module is available:
go get github.com/apache/fory/go/fory
Rust: Ensure fory crate is in Cargo.toml:
[dependencies] fory = "0.13"
C++: Ensure Fory headers are in include path.