Multi-File Projects
Arden supports organizing code into multi-file projects using a project configuration file.
Project Structure
An Arden project consists of:
my_project/
├── arden.toml # Project configuration
├── src/ # Source directory
│ ├── main.arden # Entry point
│ ├── utils.arden # Utility functions
│ └── lib.arden # Library code
└── README.md # Documentation
Creating a New Project
arden new my_project
cd my_project
arden run
This creates:
arden.toml- Project configurationsrc/main.arden- Entry point withmain()functionREADME.md- Project documentation
Project Configuration (arden.toml)
name = "my_project"
version = "1.0.0"
entry = "src/main.arden"
files = [
"src/utils.arden",
"src/main.arden"
]
output = "my_project"
opt_level = "3"
output_kind = "bin"
link_libs = ["ssl"]
link_search = ["native/lib"]
link_args = ["-Wl,--as-needed"]
Configuration Fields
| Field | Required | Description |
|---|---|---|
name |
Yes | Project name |
version |
Yes | Project version |
entry |
Yes | Entry point file (contains main()) |
files |
Yes | List of all source files to compile |
output |
No | Output binary name (default: project name) |
opt_level |
No | Final Clang optimization level: 0, 1, 2, 3, s, z, or fast (default: 3) |
target |
No | Target triple (optional) |
output_kind |
No | Final artifact kind: bin, shared, or static (default: bin) |
link_libs |
No | Extra libraries passed to Clang as -l<name> |
link_search |
No | Extra library search paths passed as -L<path> |
link_args |
No | Extra raw linker arguments forwarded to Clang |
Path safety:
entryand every path infilesmust resolve inside the project root.- Paths that escape through
..segments or symlinks are rejected during validation. outputmust also stay inside the project root and must not collide witharden.toml, the configured entry file, or any file listed infiles.- Project auto-discovery only treats a real
arden.tomlfile as the project marker; a directory namedarden.tomlis ignored. - Source-derived namespaces also reject invalid or keyword-named path segments, so file and folder names must stay valid Arden identifiers.
- Import aliases and namespace segments also reject reserved keywords, except terminal built-in variants such as
app.Option.None.
Project Commands
Build Project
arden build # Debug build
arden build --release # Optimized build
Run Project
arden run # Build and run
arden run --release # Optimized build and run
arden run arg1 arg2 # Pass arguments
Check Project
arden check # Check entry point
arden check src/lib.arden # Check specific file
Format Project
arden fmt # Format files listed in arden.toml
arden fmt --check # CI mode, fails if files need changes
arden fmt src/ # Format a specific directory tree
Show Project Info
arden info
Output:
Project Information
Name: my_project
Version: 1.0.0
Entry: src/main.arden
Output: my_project
Output Kind: Bin
Opt Level: 3
Target: native/default
Root: /path/to/project
Source Files:
- src/utils.arden
- src/main.arden
Optimization Behavior
- Project builds (
arden build,arden runin a project) useopt_levelfromarden.toml. - Valid values are:
0,1,2,3,s,z,fast. - If
opt_levelis missing, Arden defaults to3. - If
opt_levelis present but invalid, Arden now rejects the config with a direct validation error instead of silently changing optimization behavior. - If
targetis set inarden.toml, Arden forwards it to Clang as--target <triple>. - When
targetis set, host-native tuning flags are skipped to keep target/toolchain compatibility. output_kind = "shared"emits a shared library, andoutput_kind = "static"emits a static archive.link_libs,link_search, andlink_argslet project builds declare native link requirements inarden.toml.- Single-file mode (
arden compile file.arden,arden run file.arden) defaults to maximum-performance settings.
How It Works
- AST Build Pipeline: All files listed in
filesare parsed and combined as declarations in one project AST. - Import Checking: Cross-file calls are validated by the import checker. Use explicit
importstatements when calling functions from other namespaces/modules. - Deterministic Symbol Mangling: Top-level function/class/module symbols are rewritten to namespace-qualified internal names during project build.
- Scope-Aware Rewrite: Local bindings (parameters,
letvariables, loop vars, lambda params, match bindings) are never rewritten as imported/global symbols. - Collision Safety: Duplicate top-level function/class/module names across namespaces are rejected during project analysis.
- Entry Point: The
entryfile must contain themain()function. - Compilation: Project is compiled to a single binary.
Best Practices
Organize by Functionality: Group related functions into files
math.arden- Mathematical functionsstring.arden- String utilitiesio.arden- Input/output operations
Use src/ Directory: Keep source files organized in a directory
Entry Point: Keep
main.ardenminimal, delegate to other modulesDocumentation: Add README.md to explain project structure
Example Projects
See examples/starter_project/ for the minimal starter example.
See examples/showcase_project/ for a larger project-mode showcase that combines:
- cross-file packages
- nested modules
- interfaces and inheritance
- generics and enums
- async/await plus
await_timeout - file I/O and interpolation-heavy reporting
# arden.toml
name = "multi_file_demo"
version = "1.0.0"
entry = "src/main.arden"
files = [
"src/math.arden",
"src/strings.arden",
"src/main.arden"
]
output = "multi_file_demo"
output_kind = "bin"
// src/math.arden
function factorial(n: Integer): Integer {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
// src/main.arden
import std.io.*;
function main(): None {
result: Integer = factorial(5);
println("5! = " + to_string(result));
return None;
}
Single-File Mode
You can still compile single files without a project:
arden compile file.arden
arden run file.arden
Note: When in a project directory, the compiler will warn you to use arden build instead.