Creating Flame Packages
Creating a package in Flame allows you to bundle reusable Flame scripts, custom annotations, and even native Rust plugins into a single, distributable unit. When you distribute a Flame package (e.g., via GitHub), consumers can easily pull it into their projects and benefit from full IDE support and seamless native interop.
1. Package Configuration (flame.toml)
Section titled “1. Package Configuration (flame.toml)”To declare that your project is a package (rather than an executable application), set the type to "pkg" in your flame.toml file.
[project]name = "my_package"version = "0.1.0"type = "pkg"
# Optional: define a local Rust plugin bundled with this package[plugins]native_core = "./native"When type = "pkg", running flame build will generate a standalone, self-contained package folder inside target/<profile>/pkg/my_package that is ready for distribution.
2. Standard Directory Structure
Section titled “2. Standard Directory Structure”A complete Flame package typically follows this directory structure:
my_package/├── flame.toml├── src/│ └── main.fm # Main entry point for the package├── native/ # (Optional) Local Rust plugin directory│ ├── Cargo.toml│ └── src/│ └── lib.rs└── test/ # Test files └── my_test.fm3. Documenting Your Package
Section titled “3. Documenting Your Package”To provide documentation for consumers when they hover over your package name in an import statement, use the package keyword along with a @Docs annotation at the top of your src/main.fm file.
@Docs("# My PackageThis package provides a collection of useful functions and native plugins.")package my_package
import native.coreWhen a user writes import my_package and hovers over my_package, they will see these custom docs instantly.
4. Exporting Functions and Annotations
Section titled “4. Exporting Functions and Annotations”For consumers to use your package’s features, you must explicitly export them in your Flame scripts. You can export functions, structs, enums, and even custom annotations.
import native.core
// Export a custom annotationexport annotation MyAnnotation()
// Export a structexport struct Config { pub key: String}
// Export a function that uses your local native pluginexport fn process_data(config: Config) -> String { // Calling the native plugin bundled inside your package core.process(config.key)}When a user imports your package, only the exported symbols will be available in their environment.
5. Bundling Local Rust Plugins
Section titled “5. Bundling Local Rust Plugins”Flame makes it incredibly easy to bundle native Rust plugins inside your package.
- Create the Rust Plugin: Run
fmp new --plugin <plugin_name>(orfmp new -p <plugin_name>) to scaffold a new Rust plugin in the./nativedirectory. (Note: Ensure the plugin name is different from your Flame package name). - Register it: Run
fmp add --plugin ./native(orfmp add -p ./native) to register the plugin inflame.tomlunder[plugins]. The plugin name is automatically read fromnative/Cargo.toml. - Use it: Import it in your Flame scripts using the
native.prefix and its registered name (e.g.,import native.core).
6. Configuring and Running Tests
Section titled “6. Configuring and Running Tests”Testing your package ensures its reliability before distribution. Flame includes a built-in testing framework that seamlessly resolves your package’s modules.
Write your tests in the test/ directory. You can easily import your package’s source code by importing main or specific files from the src/ directory.
import main
@Testfn test_process_data() { let conf = main.Config { key: "test_key" } let result = main.process_data(conf)
assertEq(result, "processed_test_key")}Run your tests using the Flame CLI:
fmp testFlame’s package resolution system is smart enough to resolve import main inside the test/ folder directly to your src/main.fm file, providing full IDE autocomplete and diagnostics during test development.
7. Building and Distributing
Section titled “7. Building and Distributing”When you are ready to distribute your package, simply run:
fmp buildBecause type = "pkg", Flame acts as a package bundler. It will create a directory at target/pkg/my_package containing:
- Your
flame.tomlmanifest. - Your entire
src/directory. - Generated
.fmiinterface files from your local plugins.
Publishing to GitHub
Section titled “Publishing to GitHub”You don’t need a centralized package registry to distribute your package! Just push your repository to GitHub.
Consumers can install your package using the package manager:
fmp add github.com/username/my_package@v1.0.0# or declare in flame.toml and run:fmp installFlame fetches the package natively, caches the Flame sources and .fmi interface files, and makes your package functionality instantly available. Consumers never need to manually copy Rust source code or manage Cargo files in their applications. During fmp build, Flame’s dependency analysis automatically integrates only the required native plugins into that application’s specialized runtime.
