Projects, products, and dependencies
Chapter 4 introduced the daily project commands. This chapter explains the contracts that make a project deterministic and suitable for larger software.
Discovery
Project commands search the current directory and then its parents for the nearest tulam.project.tl. --project PATH selects a directory or manifest explicitly. All paths are canonicalized before source or dependency discovery.
Typed manifest boundary
Every manifest begins:
module Project;
import Tulam.Build.V1;
value project : Project = Project { ... };Pure helper functions and values are allowed. No other import is permitted at bootstrap time. Evaluation is pure, deterministic, total within fixed budgets, and isolated from filesystem, network, environment, clocks, effects, intrinsics, and targets.
Product kinds
Librarynames source roots and root modules.Executablenames an entry module and definition.TestSuiteandBenchmarkare runnable products with entries.
Each product explicitly lists package dependencies it may import. A transitive dependency is not automatically visible.
Profiles
A profile selects ordered target identifiers plus optimization, debug information, and floating contraction settings. llvm.native is the current provider. Profiles describe artifacts; they do not inject target conditionals into source.
Local and Git dependencies
Local dependencies point at another project. Git dependencies require a full 40- or 64-hex commit identifier; branches, tags, abbreviations, and version ranges are rejected. Dependency projects expose an unambiguous library product.
Locking and offline replay
tulam.lock is canonical JSON recording manifest and dependency identity plus content hashes. --locked verifies without rewriting. --offline forbids Git acquisition and requires matching local checkouts.
Build outputs
Executables default to:
.tulam/build/PROFILE/PRODUCT/PRODUCT
Libraries are currently checked and consumed from source. Serialized typed interfaces, standalone library artifacts, and definition-level incremental identity belong to the separate-compilation phase.
Inspection
Use project show to see normalized selection and project graph for the dependency-first reachable module graph. Project failures use stable TLC-PROJECT-* diagnostics before later compiler stages consume invalid state.
Common mistakes
Do not import application code into the manifest, name a Git branch instead of an exact revision, depend on an undeclared transitive package, or expect a library product to emit a serialized artifact in the current phase.
Recap
The typed manifest selects products, profiles, and exact dependencies inside a restricted pure boundary. Discovery, locks, and hashes make that selection reproducible.
Authoritative details: Project Design.