Library Compilation
Djinn supports two library formats:
.ll— Raw LLVM IR, requires source or--std-declfor type information.djlib— Self-contained library with metadata + bitcode, works without source code
.djlib Libraries (Recommended)
A .djlib file packages LLVM bitcode alongside a JSON metadata blob containing all type definitions, function signatures, macros, and attributes. Consumers can type-check, call functions, and use types without needing the library source code.
Creating a .djlib
Set the output filename with .djlib extension:
djinn std/ -o std.djlib -out buildOr via djinn.proj:
project: "my-lib"
version: "1.0.0"
compiler:
output:
file: "mylib.djlib"
directory: "build"
libs: []The .djlib extension automatically enables library mode (no main() required).
Using a .djlib
Link with -l:
djinn playground/ -l build/std.djlibOr via djinn.proj:
compiler:
libs:
- ./build/std.djlibWhen using .djlib libraries, the standard library source is not loaded — all types and functions come from the library metadata and bitcode.
What's Inside a .djlib
A .djlib is a binary file with three sections:
[Header 16 bytes]
[Metadata — JSON with all type information]
[LLVM Bitcode — compiled code]The metadata includes:
- Structs — fields, methods, properties, generic parameters, attributes, interfaces implemented
- Functions — signatures, parameters, async/constexpr flags
- Enums — variants with payload types, generic parameters
- Interfaces — method signatures, generic parameters
- Macros — rules, fragment types, token streams (fully functional in consumer)
- Extern functions — C FFI declarations with ABI info
- Impl blocks — operator overloads and interface implementations
- Attributes — declarations with target flags and schema fields
- Constants — constexpr/consteval values
- Static variables — global variables with types and mutability
How It Works
1. Compiler reads .djlib header + metadata
2. Type names registered in parser (so user code can reference library types)
3. Symbols injected into binder (structs, functions, enums, interfaces)
4. User code is parsed and bound with full access to library types
5. Generator emits LLVM declarations for library symbols
6. Bitcode from .djlib is linked into the final module
7. LLVM optimizer + clang produce the final binaryThe compiler generates declare statements for library functions (not define) — the actual implementations come from the bitcode during linking. This means zero code duplication.
.ll Libraries (Legacy)
Raw LLVM IR linking is still supported for advanced use cases.
Compiling a .ll Library
Use --lib mode to compile without requiring a main() function:
djinn --lib --no-std -c -r std/Or configure via djinn.proj:
compiler:
library-mode: true
output:
file: "mylib"
directory: "build"
libs: []What --lib does
- Skips
main()wrapper generation - Skips async runtime initialization (coro wrappers, event loop)
- All functions and struct types are exported with
ExternalLinkage - Output is a
.llfile ready for linking
Linking .ll Libraries
Use -l to link pre-compiled .ll files:
djinn -l build/mylib.ll main.djinnMultiple libraries can be linked:
djinn --std-decl -l build/std.ll -l build/mylib.ll main.djinnDeclaration-Only Mode (--std-decl)
When linking a pre-compiled .ll, you need --std-decl to get type information without re-compiling the library source:
# Step 1: Compile the library
djinn --lib --no-std -c -r std/
# Step 2: Use it with declarations only
djinn --std-decl -l build/std.ll main.djinnThis is unnecessary with .djlib — the metadata already contains all declarations.
Generic Deduplication
Monomorphized generic functions (e.g., arr<i32>::push) use LinkOnceODR linkage with COMDAT groups. If both a library and user code instantiate the same generic type, the linker keeps one copy — no duplicate symbol errors.
TypeInfo Across Modules
TypeInfo globals also use LinkOnceODR + COMDAT. Type IDs are computed via FNV-1a hash of the type name, which is deterministic. The same type compiled in different modules produces the same ID, ensuring is expressions work correctly across linked modules.
Project File Reference
Library-related settings in djinn.proj:
compiler:
library-mode: true # Compile as library (no main required)
reflection-mode: all # none | annotated | all
output:
file: "mylib.djlib" # .djlib = auto library mode + metadata
directory: "build"
libs:
- std # "std" = djinn stdlib from source
- ./vendor/math.djlib # .djlib = library with metadata
- ./vendor/legacy.ll # .ll = raw LLVM IR linkingCLI Flags Reference
| Flag | Description |
|---|---|
-o file.djlib | Output as .djlib (auto-enables library mode) |
--lib | Library mode (skip main, runtime) |
--no-std | Don't include standard library source |
--std-decl | Include std declarations only (use with -l .ll) |
-l file.djlib | Link .djlib library (metadata + bitcode) |
-l file.ll | Link raw LLVM IR module |
--bundle | Bundle all namespaces into single output |
-c | Compile only (don't generate binary) |
--reflect-all | Generate TypeInfoExt for all types |
--reflect-annotated | Generate TypeInfoExt for [Reflect] types only |