Standard Library Build Process¶
← Back to Documentation | Architecture
Documentation for building and maintaining the Sushi standard library.
Overview¶
The standard library uses a different build process than user libraries:
| Aspect | Standard Library | User Libraries |
|---|---|---|
| Source | Python code generating LLVM IR | Sushi source code |
| Format | Raw .bc (LLVM bitcode) |
.slib (bitcode + metadata) |
| Build tool | build.py script |
./sushic --lib |
| Metadata | Built into compiler | Embedded in .slib file |
This design allows the stdlib to use low-level LLVM features not exposed in the Sushi language.
Directory Structure¶
sushi_lang/sushi_stdlib/
├── build.py # Build script
├── src/ # Python source modules
│ ├── collections/ # strings.py
│ ├── io/ # stdio.py, files.py
│ ├── sys/ # env.py, process.py
│ ├── math.py
│ ├── time.py
│ └── random.py
├── generics/ # Generic type emission (List, HashMap, etc.)
└── dist/ # Built bitcode files
├── darwin/ # macOS binaries
│ ├── collections/strings.bc
│ ├── core/primitives.bc
│ ├── io/stdio.bc
│ ├── io/files.bc
│ ├── sys/env.bc
│ ├── sys/process.bc
│ ├── math.bc
│ ├── time.bc
│ └── random.bc
└── linux/ # Linux binaries
└── (same structure)
Building the Standard Library¶
Prerequisites¶
- Python 3.10+
- llvmlite (installed via
uv sync) - LLVM 20 (for native target support)
Build Command¶
From the project root:
python sushi_lang/sushi_stdlib/build.py
Output:
============================================================
Sushi Standard Library Build Script
============================================================
Project root: /path/to/sushi
Build output: /path/to/sushi/sushi_lang/sushi_stdlib/dist
Detected platform: x86_64-apple-darwin
Architecture: x86_64
OS: darwin
Vendor: apple
Building stdlib for darwin...
Output directory: /path/to/sushi/sushi_lang/sushi_stdlib/dist/darwin
Building collections/strings...
→ dist/darwin/collections/strings.bc
Building core/primitives...
→ dist/darwin/core/primitives.bc
Building io/files...
→ dist/darwin/io/files.bc
...
============================================================
Stdlib build complete!
Platform: darwin
Artifacts: dist/darwin
============================================================
Platform-Specific Builds¶
The build script automatically detects the current platform and generates bitcode for it. To build for a different platform, you must run the build on that platform.
Currently supported:
- darwin (macOS)
- linux
How It Works¶
Module Structure¶
Each stdlib module is a Python file that generates LLVM IR using llvmlite:
# Example: sushi_stdlib/src/time.py
import llvmlite.ir as ir
def generate_module_ir() -> ir.Module:
"""Generate LLVM IR for the time module."""
module = ir.Module(name="sushi_time")
# Declare external libc function
nanosleep_ty = ir.FunctionType(
ir.IntType(32),
[ir.IntType(64).as_pointer(), ir.IntType(64).as_pointer()]
)
nanosleep = ir.Function(module, nanosleep_ty, name="nanosleep")
# Create wrapper function
sleep_ty = ir.FunctionType(ir.IntType(32), [ir.IntType(64)])
sleep_fn = ir.Function(module, sleep_ty, name="sleep")
# Generate function body...
return module
Build Process¶
- Initialize LLVM - Set up native target
- Create module - Generate LLVM IR for each stdlib unit
- Compile to bitcode - Convert IR to
.bcfiles - Write to dist - Save platform-specific binaries
Why Not .slib Format?¶
The stdlib doesn't use the .slib format because:
- No metadata needed - Type information is built into the compiler
- Low-level access - Direct LLVM IR generation for libc interop
- Monomorphization - Generic types (List, HashMap) are emitted inline
- Simpler linking - Raw bitcode links directly with clang
Adding New Stdlib Modules¶
1. Create the Python Module¶
# sushi_stdlib/src/mymodule.py
import llvmlite.ir as ir
def generate_module_ir() -> ir.Module:
module = ir.Module(name="sushi_mymodule")
# Define types, functions, etc.
return module
2. Add to build.py¶
def build_mymodule(platform_dir: Path):
"""Build mymodule unit."""
print("Building mymodule...")
from sushi_lang.sushi_stdlib.src import mymodule
module = mymodule.generate_module_ir()
output = platform_dir / "mymodule.bc"
compile_module_to_bc(module, output)
Call it from main():
def main():
# ...existing builds...
build_mymodule(platform_dir)
3. Register in Compiler¶
Update sushi_lang/backend/stdlib_loader.py to recognize the new module for use <mymodule> imports.
Generic Types¶
Generic stdlib types (List, HashMap, Maybe, Result) use a different mechanism:
- Inline emission - Code is generated at compile time, not precompiled
- Monomorphization - Each instantiation (e.g.,
List<i32>) gets its own code - Location -
sushi_stdlib/generics/directory
These are not built by build.py because they must be instantiated for user-specific type arguments.
Troubleshooting¶
"LLVM target not initialized"¶
Run uv sync to ensure llvmlite is installed, then try again.
Platform mismatch errors¶
You cannot use macOS-built .bc files on Linux or vice versa. Build on the target platform.
Missing stdlib module¶
If use <module> fails with "unit not found":
1. Check the module exists in dist/{platform}/
2. Rebuild with python sushi_lang/sushi_stdlib/build.py
3. Verify the module is registered in the compiler
See Also¶
- Libraries - User library creation (
.slibformat) - Library Format -
.slibbinary format specification - Architecture - Compiler overview