Lasm:在 Lean 中编写经形式化验证的 Node、serverless 与 edge Web 应用
Show HN: Lasm – Write formally verified webapps in Lean for Node/serverless/edge
Lasm 是一个将 Lean 4 程序提前编译为 WebAssembly 的工具链,支持将单一 Lean 代码库部署为 Node 服务、serverless/edge 函数、WASI 模块或浏览器应用。该工具内置 Lean、Lake 及构建工具,并结合了形式化定理证明能力,提供多种模板与多平台部署支持。
文章介绍了将 Lean 4 程序编译为 WebAssembly 的工具链,并提供了多平台部署与定理证明能力,读者可据此评估其在形式化验证 Web 应用开发中的适用性。
面向 JavaScript 和 WebAssembly 世界的 Lean 4。Lasm 可以将普通的 Lean 4 程序提前(Ahead-of-Time)编译为 WebAssembly。单一的 Lean 代码库可以变成 Node 服务器、无服务器或边缘函数、WASI/Fastly 模块或浏览器应用。由于它是 Lean,你可以证明所部署代码的属性。旗舰示例 Conduit 是包含 117 个已证明定理的 RealWorld 应用。Lasm 在 npm 上发布,并自带 Lean、Lake 及其构建工具;你只需要 Node(或 Bun 或 Deno)。
npm create @lasm@latest my-app -- --template hono # then: cd my-app && npm install && npm run devAI 代理:此 README 本身是完整的。llms.txt 是简短的索引,docs/AI.md 列出了能帮你避免走弯路的规则。
如果 Lasm 对你有所帮助,我将不胜感激你的赞助(详情见下文)。
快速事实
| 事实 | 值 |
|---|---|
| 当前版本 | @lasm/cli 0.3.5(发布说明);npm view @lasm/cli version |
| 安装 | npm install -D @lasm/cli(bin: lasm),或无需安装:npx @lasm/cli …;新项目:npm create @lasm@latest |
| Lean | 恰好 4.35.0(lean-toolchain:leanprover/lean4:v4.35.0);Lasm 会安装它,构建时你不需要 elan |
| 开发于 | Linux x64/arm64 (glibc 2.34+)、macOS x64/arm64、Windows x64 |
| 编译器运行于 | Node ≥ 24(已测试 24.0.0、24.22.1、26.12.1);Bun 1.4.4 和 Deno 2.9.6(已测试,作为唯一运行时) |
| 输出 | 带有 program.wasm 的 dist/ + JS 启动器(Node);或平台包(--target …) |
| Node 应用运行于 | Node ≥ 24、来自任何构建机的 Linux x64/arm64(glibc 2.28+ 或 musl),以及构建机自身的操作系统;≥ 512 MB 内存 |
| JS/npm 互操作 | import Lasm.JS;你调用的每个函数对应一行 @[js "pkg" "export"];无预制绑定(指南) |
| Lean 中的框架 | Lasm.Fetch(HTTP,每个服务器目标)、Lasm.UI(浏览器,Elm 架构,已证明 diff)、Lasm.RPC(类型化客户端/服务器 API)、Lasm.Web(DOM 和网页 API)、Lasm.KV |
| 运行时不可用 | elab 推导、#eval 风格的求值、加载 .olean、Lean 内核(准确列表);所有这些都在构建时工作 |
| 许可证 | MIT (Lasm);模板、示例和 README 代码样本也使用 MIT-0 |
| 仓库 / 问题 | https://github.com/Millillion/lasm · 报告 bug(包含 npx lasm --version) |
平台
每一行都在 CI 中使用平台的本地运行时、镜像或模拟器进行测试。 根据项目策略,CI 绝不会部署到真实的云账户中 (各个平台的测试方式)。
| 部署到 | lasm build Main.lean --target … |
输出 | 自 |
|---|---|---|---|
| Node 服务器或程序(任何主机、Docker/Kubernetes、Cloud Run、Fly.io、Railway、Render、Heroku、DigitalOcean) | node(默认) |
dist/ → node dist/main.mjs |
0.1.0 |
AWS Lambda (.zip, nodejs24.x) |
lambda |
lambda.zip |
0.1.0 |
| AWS Lambda(容器镜像) | lasm init … --deploy lambda |
Dockerfile.lambda |
0.1.0 |
| Lambda@Edge | lambda-edge |
lambda-edge.zip |
0.1.0 |
| Vercel Functions | vercel |
.vercel/output |
0.1.0 |
| Netlify Functions | netlify |
netlify/functions/lasm |
0.1.0 |
| Azure Functions | azure |
azure-functions/ |
0.1.0 |
| Google Cloud Functions (gen2) | gcf |
gcf/ |
0.1.0 |
| Cloudflare Workers | workers |
workers/ |
0.2.0 |
| Vercel Edge | vercel-edge |
api/lasm.mjs, api/_lasm/ |
0.2.0 |
| Netlify Edge | netlify-edge |
netlify/edge-functions/lasm.mjs |
0.2.0 |
| Deno Deploy | deno-deploy |
deno/main.mjs |
0.2.0 |
| Supabase Edge Functions | supabase-edge |
supabase/functions/<name>/ |
0.2.0 |
| Bun (≥ 1.3.14) / Deno (2.x) | bun / deno |
bun/main.mjs / deno/main.mjs |
0.2.0 |
| Fastly Compute | fastly |
bin/main.wasm, pkg/<name>.tar.gz |
0.3.0 |
WASI (wasmtime, wasmer, node:wasi) |
wasi |
wasi/main.wasm |
0.3.0 |
wasi-http (wasmtime serve, Spin) |
wasi-http |
wasi-http/main.wasm |
0.3.0 |
| 浏览器(Chrome、Edge、Firefox、Safari) | browser(或 Vite 插件 @lasm/cli/vite) |
dist/ 静态网站 |
0.3.0 |
Node 构建拥有 Lean 的完整运行时(线程、文件、进程、套接字)。边缘、Bun/Deno、WASI 和浏览器构建运行单线程的 Lean,没有套接字或进程(也没有文件,WASI 除外);Lean 的其余部分均可正常工作。
从这里开始
| 我想构建…… | 运行 | 然后查看 |
|---|---|---|
| 命令行程序 | npm create @lasm@latest my-tool |
examples/hello、examples/wasi-cli |
| Node 上带 npm 框架的 REST API | npm create @lasm@latest my-api -- --template hono(或 express、fastify) |
examples/js-crud(Postgres + JWT、Express 和 Hono) |
| 纯 Lean 服务器(无 npm) | npm create @lasm@latest my-api -- --template fetch(任意目标)或 --template std-http(Node,亦可本地 Lean) |
examples/fetch;std-http 模板 |
| 一个无服务器函数(Lambda、Vercel、Netlify、Azure、GCF) | npm create @lasm@latest my-fn -- --template hono --deploy lambda-zip(或 vercel、netlify、azure、gcf、lambda-edge) |
docs/deploy |
| 一个边缘函数(Workers、Vercel/Netlify Edge、Deno Deploy、Supabase) | npm create @lasm@latest my-edge -- --template hono --deploy workers(或 fetch) |
examples/edge-pure、docs/EDGE.md |
| 一个 Fastly、WASI 或 Spin 服务 | npm create @lasm@latest my-svc -- --template fetch --deploy fastly(或 wasi-http、spin、wasi) |
examples/fetch、docs/WASI.md |
| 一个浏览器应用 | npm create @lasm@latest my-web -- --template web |
examples/ui(计数器、带证明的 TodoMVC、功能演示、基准测试) |
| 一个完整的现实世界应用(API、浏览器前端、SQL、鉴权),带证明,运行在 Node、Workers 或 Bun 上 | cd examples/conduit && npm install && npm run build && npm start |
examples/conduit,旗舰示例(见下方) |
| 一个带有已验证 API 的全栈应用 | npm create @lasm@latest my-app -- --template fullstack |
templates/fullstack |
要在 Lean 中调用 npm 包或 fetch |
添加 import Lasm.JS 以及每个函数一行 @[js] |
examples/js-fetch、JS 绑定 |
| 要在 Bun 或 Deno 上运行 | bun create @lasm my-app --template hono / deno run -A npm:@lasm/create my-app --template hono |
docs/BUN_DENO.md |
每个示例都包含一个带有一条命令运行说明的 README;examples/README.md 列出了所有这些示例。
旗舰示例:Conduit,包含 117 个已证明的定理
examples/conduit 是 Conduit,即 RealWorld 应用(一个 Medium 克隆版),完全用 Lean 编写:包括 REST API、服务端渲染的浏览器应用以及证明。
- 关于实际运行代码的 117 个定理,经检查不包含
sorry,且仅使用 Lean 的标准公理(npm run proofs;PROOFS.md 用通俗易懂的英文列出了每一个定理)。它们涵盖了授权(只有作者可以修改自己的文章和评论)、关注与收藏、永不冲突的 slug、永不跳过或重复的分页、客户端与服务器共享的验证(应用绝不会发送服务器会拒绝的内容)、JSON 往返以及 Markdown 链接安全性。这些端点是针对函数的Store编写的,并且证明在表格模型上运行了相同的代码。 - 受信任但未证明的部分:每个 SQL 语句都符合其模型所描述的行为、JSON 文本层、请求并发性,以及 Lean、Lasm 和 JavaScript 运行时。对整个 RealWorld 规范的符合性是通过测试而非证明来保证的。
- API:官方 RealWorld API 套件在 Node(
node:sqlite)、Cloudflare Workers(D1)和 Bun(bun:sqlite)上未作修改即可通过(13 个文件中的 13 个,154 个请求)。每个目标都有一个手写的@[js]绑定模块。 - 前端:在 RealWorld 官方模板上的
Lasm.UI,具备服务端渲染、水合作用(hydration)以及在 Lean 中解析的 Markdown。官方的 Playwright 端到端套件在配备 Chromium、Firefox 和 WebKit 的 Node 上,以及配备 Chromium 的 Workers 和 Bun 上通过,无需重试。
所有这些都在 CI 中运行(conduit.yml,运行编号 40615274657,使用 @lasm/cli 0.3.4)。
cd examples/conduit npm install # @lasm/cli, Hurl and Playwright (the official suites' runners) npm run build && npm start # http://localhost:3000: the app and its API on Node npm run proofs # check all 117 theorems npm test # the official API suite (also test:workers, test:bun) npx playwright install chromium && npm run test:e2e # the official end-to-end suite npm run build:workers && npx wrangler dev # Cloudflare Workers with local D1 npm run build:bun && npm run start:bun # Bun with bun:sqlite
60 秒快速开始
单文件无需项目。将这个完整的程序保存为 Main.lean:
def main : IO Unit := do IO.println s!"Hello from Lean! 2 + 3 = {2 + 3}"
npx @lasm/cli Main.lean # builds and runs: Hello from Lean! 2 + 3 = 5 npx @lasm/cli build Main.lean # writes dist/; run it with: node dist/main.mjs
在新机器上的首次构建会获取一次 Lean 和构建工具(大约 250–275 MB;在 Linux CI 运行器上首次构建耗时 19 秒)。后续对单行代码更改的开发构建大约需要 1–2 秒。
操作指南
每个指南都是完整的:创建、开发、构建、部署。Lasm 从不安装或启动平台自身的 CLI(wrangler、vercel、fastly 等);这些需要由你来运行。npm run dev 是 lasm dev:它在每次保存后大约 2 秒重新构建并重启服务器,并且在出现类型错误时保持上一个良好的构建继续运行。
Node 服务器(Hono;同时支持 express、fastify、std-http、fetch)。
npm create @lasm@latest my-api -- --template hono cd my-api && npm install npm run dev # http://localhost:3000/hello/Ada npm run build && npm start # dist/ needs only Node 24+ docker build -t my-api . && docker run -p 8080:8080 my-api # the generated Dockerfile
AWS Lambda / Vercel / Netlify / Azure / Google Cloud Functions。
npm create @lasm@latest my-fn -- --template hono --deploy lambda-zip # or vercel, netlify, azure, gcf, lambda-edge cd my-fn && npm install npm run build:lambda # dist/ and lambda.zip (handler lasm-lambda.handler) # deploy lambda.zip with the AWS console, aws CLI or SAM; recipes: docs/deploy/lambda.md
Cloudflare Workers(以及 Vercel Edge、Netlify Edge、Deno Deploy、Supabase)。
npm create @lasm@latest my-edge -- --template hono --deploy workers cd my-edge && npm install npm run build:workers # workers/ (wrangler.toml came from lasm init) npx wrangler dev # local workerd; npx wrangler deploy to publish
Fastly Compute、WASI、Spin。
npm create @lasm@latest my-svc -- --template fetch --deploy fastly --deploy spin cd my-svc && npm install npm run build:fastly && fastly compute serve # Viceroy on http://127.0.0.1:7676 npm run build:wasi-http && spin up # or: wasmtime serve wasi-http/main.wasm
浏览器应用。
npm create @lasm@latest my-web -- --template web cd my-web && npm install npm run dev # http://127.0.0.1:5173, live reload npm run build # dist/: a static site for any host or CDN
全栈(服务端 + 浏览器 + 已验证 API)。
npm create @lasm@latest my-app -- --template fullstack cd my-app && npm install npm run dev # one URL: http://127.0.0.1:3000 npm run build && npm start # Node; also build:workers, build:bun, build:deno
编辑器。每个项目运行一次 npx lasm editor;lasm init、lasm dev 和
lasm build 也会这样做。随后 Lean 编辑器(VS Code 的 Lean 4 扩展)会解析
import Lasm.*(详情)。
Lean 中的整个栈,经过验证
fullstack 模板是一个包含服务端(Lasm.Fetch)、浏览器应用(Lasm.UI)以及两者间 API(Lasm.RPC)的 Lean 项目。请求必须满足的规则在 Shared.lean 中编写并证明了一次,双方都会导入该文件(templates/fullstack):
-- Shared.lean @[irreducible] def checkTitle (title : String) : Except String Unit := let n := (clean title).length if n = 0 then .error "Write something first." else if n > maxTitle then .error s!"Keep it under {maxTitle} characters." else .ok () /-- Proved once, holds in the browser and on the server. -/ theorem checkTitle_ok {title : String} (h : checkTitle title = .ok ()) : 0 < (clean title).length ∧ (clean title).length ≤ maxTitle := by unfold checkTitle at h by_cases h0 : (clean title).length = 0 · simp [h0] at h · by_cases h1 : (clean title).length > maxTitle · simp [h0, h1] at h · omega def addTodo : Endpoint NewTodo Todo := { name := "addTodo", validate := fun r => checkTitle r.title }
-- Server.lean: storing a todo demands the proof that its title passed the check, -- and `addTodo.serve` hands the handler that proof (`ok`) after re-validating. def Store.add (s : Store) (title : String) (_ : checkTitle title = .ok ()) : Store × Todo := let t := { id := s.next, title := clean title, done := false } ({ todos := s.todos.push t, next := s.next + 1 }, t) addTodo.serve fun req ok => do let (s, t) := (← load kv).add req.title ok save kv s return .ok t
-- Client.lean: a theorem about the browser app: it never sends an invalid title. theorem add_invalid (m : Model) (e : String) (h : checkTitle m.draft = .error e) : (update .add m).2.effects = [.msg (.added (.error (.invalid e)))] := addTodo.call_invalid { title := m.draft } Msg.added "" e h
证明所在的位置以及如何进行检查。
| 证明 | 位置 | 检查方式 |
|---|---|---|
你的定理(如 checkTitle_ok、add_invalid) |
你的 .lean 文件 |
每个 lasm build/lasm dev(由 Lean 进行精化;证明错误即为构建错误);纯模块也使用 lake build |
Lasm.RPC:处理程序仅在通过 validate (Endpoint.decodeRequest_valid) 的请求上运行;客户端从不发送未通过该验证的请求 (Endpoint.call_invalid) |
library/Lasm/RPC | 每次构建时编译到 Lasm 的库中 |
Lasm.UI:DOM diff 相对于 DOM 模型是正确的,包含带键的移动(diff_correct、mount_correct、session_correct) |
library/Lasm/UI/Proofs(约 1,260 行,无 sorry,仅标准公理) |
检出版本中的 node scripts/ui/lean-tests.mjs(CI:ui.yml) |
| Conduit:关于授权、关注、收藏、slug、分页、共享验证、JSON 往返和 Markdown 链接安全性的 117 个定理 | examples/conduit/Proofs,列在 PROOFS.md 中 | examples/conduit 中的 npm run proofs(无 sorry,仅标准公理;CI conduit.yml) |
| TodoMVC:每个可达模型都是有效的 | examples/ui/todomvc/Todo.lean | lasm build;CI ui.yml |
未经验证,在 CI 中进行测试:客户端与服务端之间的 JSON/HTTP 传输、将补丁应用到真实 DOM 的 JavaScript、Lasm 编译器与运行时、以及浏览器。Lean 自身的编译器是受信任的,如同任何 Lean 程序一样(UI.md、RPC.md)。
从 Lean 调用 JavaScript 和 npm
用单行代码声明你调用的每个 JavaScript 函数;Lean 类型说明了值的转换方式。一个完整的程序(Node 的全局 fetch):
import Lasm.JS open Lasm.JS /-- `await fetch(url, init)` (Node's global fetch) -/ @[js "globalThis" "fetch"] opaque fetch : String → Data → IO Value def main : IO Unit := do let response ← fetch "https://example.com" (obj []) IO.println s!"{← response.get "status" Nat}: {(← response.callMethodAwait "text" #[] String).length} characters"
编写绑定(bindings)的规则:
@[js "module" "export"] opaque name : A → B → IO R绑定module.export。该模块是一个 npm 包("marked")、Node 内置模块("node:fs"),或者是用于全局变量的"globalThis"。"new Hono"调用构造函数,而""是模块自身的值。- 对于立即返回的值,类型以
IO R结尾;对于 Promise,以Async R结尾。Async绑定在等待(awaited)时不会占用 Lean 线程。 - 使用
String、Nat、Int、Float、Bool、ByteArray、Array、List、Option、元组、Data(任何 JS 数据)或Value(JS 对象引用:get、callMethod、callMethodAwait)。你自己的结构体可以通过deriving ToJS, FromJS进行转换。 Function.ofFn/Function.ofFnReply将 Lean 函数转换为 JS 回调。框架处理程序会使用它们(参见hono、express和fastify模板)。npm install是 lakefile 旁边的包。lasm build针对已安装的包(Lasm.JS binding check failed: … export "x" is missing)检查每个绑定,并将生产依赖项复制到dist/node_modules中。- 每次调用都会从 Lean 线程跨越到 Node 的主线程(约 24 µs),因此请倾向于使用一个粗粒度调用,而不是多个小调用。
完整指南,包含 Express、Hono、pg、jose 和 fetch 示例以及代理检查清单:docs/JS_BINDINGS.md。
测得的数据
所有数据均来自免费 GitHub 运行器(4-CPU AMD EPYC,Linux x64)上的 CI,候选版本 0.1.0-experimental.40494203854 (2026-10-27),除非另有说明。完整表格、方法与注意事项:BENCHMARKS.md。
| 指标 | 数值 |
|---|---|
| Node:Hono + Lean 处理程序,冷启动到首次 HTTP 响应 | 159 ms(纯 Node http:快 4.1 倍) |
| Node:Hono + Lean 处理程序,吞吐量 / p99 延迟 | 24,911 req/s / 4.2 ms(纯 Node http:103,134 req/s,即 0.24 倍) |
| Node:Express + Lean 处理程序,吞吐量 | 18,678 req/s |
Node:Hono 应用 program.wasm (brotli) / dist/ |
166 KiB / 8.5 MiB 另加 1.4 MiB node_modules |
| Node:内存,Hono 应用空闲 / 负载下 | 148 MiB / 329 MiB RSS |
| Lean → JS 调用往返(p50) | 24 µs |
| Cloudflare Workers:Hono 应用包 | 1.40 MiB, 245 KiB gzip(限制 64 MiB;workers 运行 40128600109) |
| 浏览器:计数器应用总传输量 / 首帧(Chromium) | 152 KiB brotli / 30 ms(browser 运行 40288509500) |
| 浏览器:js-framework-benchmark 对比手写 JS | 所有操作均在 1.7× 以内,多数在 1.2× 以内(browser 运行 40302274897) |
WASI:在 Fastly 的 Viceroy 上每个请求对应 Lasm.Fetch 模块 |
0.90 MiB / 1.17 ms,每个请求使用全新实例(wasi 运行 40293231963) |
| 构建:干净的 Hono 构建 / 单行更改后的开发重建 | 4.7 s / 2.0 s |
npm install @lasm/cli:下载 / 已安装;首次构建后的工具缓存 |
71 MiB / 403 MiB;2.5 GB |
Node 上的 Lean 需要为 WebAssembly 及其线程付出开销。冷启动是 CPU 密集型的,因此它在小型无服务器 CPU 份额上会增长,并且每个 JavaScript 调用都会跨越线程。纯 Lean Std.Http 在 Node 上较慢(1,290 req/s),因此生产环境 HTTP 请使用 Hono、Express、Fastify 或 Lasm.Fetch。带有数千位数字的算术运算比原生 Lean 慢(无 GMP)。
已知限制
- 仅限 AOT(预先编译)。已部署的程序在运行时不能进行 Lean 的精化(elaborate)、求值或编译,不能加载模块数据或插件,也不能使用 Lean 的 C++ 编译器/内核(确切列表)。证明、策略、宏和
#eval照常在编译时运行。 - 仅限 Lean 4.35.0。其他
lean-toolchain版本会被拒绝并显示提示信息。 - Node:请给应用至少 512 MB 内存;它预留约 22 GB 虚拟地址空间。无法链接预构建的原生库(
-l、共享库);软件包中自带的 C 源码会为你进行编译。 - Edge、Bun/Deno、浏览器、WASI:单线程 Lean;无套接字、进程或信号;除 WASI 外无文件。在浏览器中,阻塞等待会停止应用,除非它是为带有 JSPI 的浏览器使用
--suspend jspi构建的;请使用Async。 - 无预制绑定(针对 npm 软件包);
Lasm.Web涵盖核心 Web 平台。 - 编辑器:在进行上述
npx lasm editor操作后,编辑器中的Lasm.*导入才能解析。 - 平台:不支持 Windows ARM64 以及 Alpine/musl 构建机器(构建的应用可在 Alpine 上运行)。托管平台使用其本地工具进行测试,从不使用真实账户。
文档
- 开始:入门指南 · 所有文档 · 面向 AI 代理 · llms.txt
- 指南:服务器与 npm 互操作 · 无服务器与容器 · edge · Bun 和 Deno · 浏览器与 Lasm.UI · 全栈 (Lasm.RPC) · Lasm.Fetch · WASI 和 Fastly · 编辑循环
- 证据:基准测试 · 应用运行位置 · 语言覆盖率 · 兼容的 Lean 软件包 · 决策
支持 Lasm
如果 Lasm 对你有所帮助,或者你希望看到它成功,我将不胜感激你的赞助:github.com/sponsors/lastmjs。这支持了我以及针对 Lasm 和其他 Millillion 项目的工作。我的第一个目标是每月 250 美元,这足够为一个 Lasm 专用的 Claude Code 账户提供资金。你也可以通过给仓库点星、试用它以及报告崩溃问题来提供帮助。
参考
以下所有内容都是精确的契约:每个命令和选项、支持的机器和平台,以及已部署的 Lean 程序绝对无法执行的操作。
CLI 参考
使用 npm install -D @lasm/cli 在项目中安装(bin 为 lasm),或直接运行而无需安装:npx @lasm/cli Main.lean。npm create @lasm 运行相同 lasm init 版本的 @lasm/cli,参数保持不变。使用来自 快速入门 的 Main.lean:
npx lasm Main.lean # build (dev profile) and run: Hello from Lean! 2 + 3 = 5 npx lasm build Main.lean # write dist/ (release profile) npx lasm --version # version, Lean, runtime and platform (for bug reports) node dist/main.mjs # run the deployment: only Node is needed npx lasm build Main.lean --target lambda # dist/ and an AWS Lambda zip
| 命令或选项 | 示例 | 效果 |
|---|---|---|
| 运行(默认) | npx lasm Main.lean |
构建(dev 配置)并运行 Lean main。plain 项目中的 npm run dev 会运行此命令。 |
| 显式运行 | npx lasm run Main.lean |
与默认命令相同。 |
| 运行 release 构建 | npx lasm Main.lean --release |
构建并运行 lasm build 部署的精确内容。 |
| 程序参数 | npx lasm Main.lean -- hello "two words" |
向 main (args : List String) 传递参数。 |
| 监视、重新构建、重启 (0.3.0) | npx lasm dev, npx lasm dev Main.lean --target workers -- arg |
监视 Lean 源码以及 Lake/npm 配置,在每次更改后重新构建(dev 配置,一个长生命周期的构建工作进程)并重启程序(--target node、bun、deno;默认:运行 Lasm 的运行时)。构建错误会连同其文件、行号和源码行一起打印出来;最后一个正常的程序会继续运行。边缘目标仅重新构建其输出目录,由平台自身的本地服务器提供服务(Lasm 从不启动平台工具或浏览器)。--target browser 以实时重载(--port、--host、--no-watch)提供应用服务;多个输出同时构建:--target node=Server.lean,browser=Client.lean。--release 构建 release 配置,--no-run 仅重新构建,rs + Enter 重新构建并重启。详情。 |
| 构建 | npx lasm build Main.lean |
写入 dist/(release 配置);不运行应用程序。 |
| Dev 构建 | npx lasm build Main.lean --dev |
更快地写入 dist/,不进行体积优化。 |
| 输出目录 | npx lasm build Main.lean --output "app dist" |
选择部署目录。lasm build Main.lean "app dist" 是一个别名。 |
| 函数平台 | npx lasm build Main.lean --target lambda |
构建 dist/,然后对其进行打包:node(默认;仅 dist/)、lambda(lambda.zip)、lambda-edge(lambda-edge.zip)、vercel(.vercel/output)、netlify(netlify/functions/lasm)、azure(azure-functions/)、gcf(gcf/)。--target=vercel 同样有效。Lasm 从不安装或启动平台的 CLI。操作指南。 |
| 边缘隔离 (0.2.0) | npx lasm build Main.lean --target workers |
使用纯 JS 主机重新链接单线程:workers(workers/)、vercel-edge(api/lasm.mjs、api/_lasm/)、netlify-edge(netlify/edge-functions/lasm.mjs、netlify/lasm/)、deno-deploy(deno/main.mjs)、supabase-edge(supabase/functions/<name>/;Asyncify,因为 Supabase 的运行时没有 JSPI)。边缘运行时内置于 @lasm/cli 中。指南:Workers、Vercel Edge、Netlify Edge、Deno Deploy、Supabase;设计与限制。 |
| Bun 和 Deno (0.2.0) | bunx --bun @lasm/cli Main.lean, deno run -A npm:@lasm/cli Main.lean, bun create @lasm my-app --template hono |
编译器以 Bun 或 Deno 作为其唯一的 JavaScript 运行时运行,并产生相同的字节。在 Bun 或 Deno 下,默认目标是该运行时:--target bun 写入 bun/main.mjs,--target deno 写入 deno/main.mjs(便携配置)。Deno 会跳过发布时间不到 24 小时的 npm 版本:发布后立即通过 --minimum-dependency-age=0。Bun 和 Deno。 |
| 浏览器 (0.3.0) | npx lasm build Main.lean --target browser |
将 dist/ 写入为静态网站:app.<hash>.js(加载器:mount(element, { flags, hydrate }),自动挂载 <div data-lasm-app>)、app.<hash>.wasm、brotli 和 gzip 副本、app.js、index.html(带有注入加载器的你的页面,或生成的页面)、你的 public/ 文件和 lasm-manifest.json。--suspend jspi 允许阻塞等待在浏览器拥有 JSPI 的地方暂停。--bundler 将 npm 导入留给打包工具;在 Vite 中:import lasm from '@lasm/cli/vite',然后 import app from './Main.lean?lasm'。来自 Lean 的 Web API:import Lasm.Web。指南:BROWSER.md、UI.md、部署。 |
| WASI、wasi-http、Fastly (0.3.0) | npx lasm build Main.lean --target wasi(或 wasi-http、fastly) |
没有 JavaScript。wasi 写入 wasi/main.wasm(wasi_snapshot_preview1:wasmtime run --dir . wasi/main.wasm,wasmer,node:wasi);wasi-http 写入 wasi-http/main.wasm,一个 wasi:http/proxy@0.2 组件(wasmtime serve,Spin);fastly 写入 bin/main.wasm 和 pkg/<name>.tar.gz(fastly compute serve/deploy)。没有套接字、进程或信号。WASI.md、Fastly。 |
| 纯 Lean 中的 HTTP (0.3.0) | import Lasm.Fetch … def main := Lasm.Fetch.serve handle |
一个 Request → Async Response 处理器为 Node($HOST:$PORT)、边缘目标、Bun、Deno、Fastly、wasi-http 和作为 CGI 的 WASI 提供服务;Lasm.Fetch.fetch 发送请求;Response.streaming 流式传输。FETCH.md。 |
| 强制重新构建 | npx lasm build Main.lean --rebuild |
忽略缓存的应用构建。 |
| 详细诊断 | npx lasm Main.lean --verbose |
显示编译器和链接器详情。 |
| 帮助 | npx lasm --help, npx lasm init --help |
显示用法;-h 是一个别名。 |
| 版本 | npx lasm --version |
打印 lasm 0.3.5 (@lasm/cli; Lean 4.35.0; Node 26.12.1; linux-x64);-v 是一个别名。 |
| 新项目 | npm create @lasm@latest my-app -- --template hono 或 npx @lasm/cli init my-app --template hono |
在新的或空目录中创建一个 Lake 项目(Main.lean、App.lean、lakefile、lean-toolchain、package.json、README.md、.gitignore,对于服务器还包括一个 Dockerfile 和 .dockerignore)。模板:参见 从这里开始。--deploy(可重复)添加平台的文件和 npm run build:<target>:lambda(Dockerfile.lambda,一个容器镜像)、lambda-zip、lambda-edge、vercel、netlify、azure、gcf;workers、vercel-edge、netlify-edge、deno-deploy(模板 hono、fetch、fullstack)、supabase-edge(hono);fastly、wasi-http、spin(fetch、fullstack)、wasi(fetch、plain)。fetch 和 fullstack 模板及其目标属于 0.3.0 版本。仅写入文件;接下来请运行 npm install。-t 是 --template 的别名;--template=hono 也可以使用。 |
| 打包现有构建 | npx lasm package --target lambda |
打包已构建的服务器(默认 dist/),用于函数平台,无需重新构建:目标和输出与 lasm build --target 相同,但 node 除外。--output PATH 用于选择输出。检查平台的大小限制。除非满足 --allow-dev,否则拒绝开发版构建。对于浏览器构建,npx lasm package dist --target browser 会对照 lasm-manifest.json 检查每个文件并写入 _headers。 |
| 编辑器支持 (0.3.0) | npx lasm editor |
使 Lean 编辑器(VS Code 的 Lean 4 扩展、任何 Lean 语言服务器客户端)解析此 Lake 项目中的 import Lasm.*:将 Lasm 的 Lean 4.35.0 及其库链接为 elan 工具链 lasm-4.35.0-…,并将其设置为该目录的 elan 覆盖(elan override unset 可撤销此操作)。当 Lasm 的 Lean 已经安装时,lasm init、lasm dev 和 lasm build 会执行相同操作,每个项目打印一行,但在 CI 中或使用 LASM_EDITOR=0 时除外。编辑器设置。 |
| 缓存修复 | npx lasm cache repair |
离线验证并移除无效工具和废弃的暂存区。拒绝处于活动状态的构建。 |
--rebuild 和 --verbose 适用于运行和构建。--output 和 --target 仅用于
构建;-- 之后的参数仅用于运行。应用程序的退出状态会
予以保留。npx lasm --version(-v)打印版本、Lean 发行版、JavaScript
运行时和平台(请将其包含在错误报告中)。没有 install、clean 或
uninstall 子命令。
构建配置文件。两者使用相同的库链接相同的程序,且都是
确定性的。release(lasm build、lasm Main.lean --release):完整的
Binaryen 大小优化;字节级可复现;用于部署的版本。dev
(lasm Main.lean、lasm dev、lasm build --dev):省略这些优化通道,并在
-O1 下编译您的模块;其行为相同,构建速度快几秒钟,
且其 program.wasm 大约大 15–20%。开发版重新构建从
项目的上一次构建开始,因此其字节可能取决于该次构建。build-info.json
记录了 "profile"。除非您传入 --allow-dev,否则 lasm package 和 lasm build --dev --target <platform>
会拒绝开发版构建。
环境变量(全部可选):
| 变量 | 示例 | 效果 |
|---|---|---|
LASM_TOOLCHAIN_CACHE |
LASM_TOOLCHAIN_CACHE=/data/lasm-cache npx lasm Main.lean |
移动托管工具缓存(默认位置)。 |
LASM_BUILD_JOBS |
LASM_BUILD_JOBS=2 npx lasm build Main.lean |
Binaryen 优化器的线程数(默认:CPU 数量,最多 8 个)。无论什么值,输出都相同。 |
LASM_EDITOR |
LASM_EDITOR=0 npx lasm build Main.lean |
0:lasm init、lasm dev 和 lasm build 不干预编辑器设置(编辑器设置)。 |
LASM_THREAD_POOL(已构建的应用;0.3.0) |
LASM_THREAD_POOL=0 node dist/main.mjs |
在 main 之前启动的 Lean 线程工作进程(0–64,默认 1)。测量数据。 |
LASM_ARTIFACT_SOURCE |
LASM_ARTIFACT_SOURCE=npm npx lasm Main.lean |
auto(默认):存在时使用 @lasm/… npm 工具包,否则使用 HTTPS;npm:从不直接下载;https:忽略 npm 包。 |
LASM_DOWNLOAD_ATTEMPTS、LASM_DOWNLOAD_CONNECT_MS、LASM_DOWNLOAD_IDLE_MS、LASM_DOWNLOAD_TOTAL_MS |
LASM_DOWNLOAD_TOTAL_MS=14400000 npx lasm Main.lean |
下载重试和超时(默认值和范围)。 |
NODE_USE_ENV_PROXY、HTTPS_PROXY、NO_PROXY、NODE_EXTRA_CA_CERTS(Node 自带) |
NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://proxy:8080 npx lasm Main.lean |
代理和私有 CA(企业网络)。 |
源码中的其他 LASM_* 变量属于维护者诊断信息,并非受支持的
接口。
安装。 npm install @lasm/cli 通过您自己的注册表、代理和缓存,为您的平台将 Lean 和构建工具作为精确锁定的 @lasm/… npm 包引入。Lake/Lean-import 数据,以及仅针对包含 C 代码的 Lake 项目的 C 层(@lasm/lean-c-<platform>),在首次使用时通过您的 npm 获取。
终端会显示进度;后续构建会复用已验证的工具和未更改的输出。在一台没有下载缓存的新机器上,CI 运行器上的首次 Hono 构建耗时为 25.7 秒(Linux x64)、27.8 秒(Linux arm64)、44.4 秒(Windows)、58.7 秒(Apple Silicon)和 141.9 秒(Intel Mac)
(构建时间,运行 40131930601)。
缓存位置与恢复:NODE_SUPPORT.md、
INSTALLATION_HARDENING.md。
仅当 Lake 项目具有 Git 或 Reservoir 依赖项时才需要 Git;Lasm 使用您 PATH 上的 git,并在缺少时提示如何安装。
现有的 Lake 项目可以直接在项目目录中使用 npx lasm build Main.lean 进行构建。在 lean-toolchain 中锁定 leanprover/lean4:v4.35.0;其他版本会被 Unsupported Lean toolchain … Lasm supports Lean v4.35.0 拒绝。按软件包列出的兼容性列表涵盖了 Batteries、Cli、LSpec、Plausible、Aesop、Qq、leansqlite、UnicodeBasic、MD4Lean、lean-zip、lean4-parser、lean-redis 等;未列出的软件包未经测试。
支持的环境
使用 Lasm(编译器)构建的机器:
| 环境 | 架构 | 状态 |
|---|---|---|
| Ubuntu 24.04 LTS | x86-64、ARM64 | 在 CI 中接受已安装软件包和复制部署验证;参考平台。 |
| 其他 Linux 发行版 | x86-64、ARM64 | 未作为构建机器进行验证;这些工具需要 glibc 2.34。Alpine/musl 不能作为构建机器(构建的应用可在其上运行)。 |
| macOS 15 | x86-64、ARM64 | 在 CI 中接受已安装软件包和复制部署验证。带有 C 代码的 Lake 项目需要 Xcode Command Line Tools SDK。 |
| Windows Server 2025 / Windows x64 | x86-64 | 在 CI 中接受已安装软件包和复制部署验证。 |
| Windows ARM64 | ARM64 | 不支持:Lean 和 Emscripten 均未发布 Windows ARM64 预构建版本。 |
| 作为编译器运行时的 Bun 1.4.4 和 Deno 2.9.6 (0.2.0) | 上述所有 | 在 CI 的全部五个平台上进行测试,在 PATH 上运行且不依赖 Node 或 npm(BUN_DENO.md)。 |
Node 24 或更高版本(已测试:24.0.0、24.22.1、26.12.1)。无引擎标志。精确测试的产物:NODE_ACCEPTANCE.md。
支持的平台
Node dist/ 需要 Node 24 或更新版本(Node 22 及更早版本会通过 This application requires Node 24.0.0 or newer 终止)以及至少 512 MB 内存。它可在 Linux x64 和 arm64(glibc 2.28+ 或 musl/Alpine)上运行(这些平台可以由任何支持的平台构建,也可以在其自身的构建机器平台上运行)。复制 dist/ 的所有内容;那里不需要 Lean 源码、npm install 或构建工具。下方的每个平台都在 CI 中通过命名的本地运行时、镜像或模拟器进行了测试;均未使用真实的云账号。完整矩阵:DEPLOYMENT.md。
| 平台 | 在 CI 中测试的环境 |
|---|---|
| Linux x64 和 arm64 (glibc 2.28+)、Node 24+ | ubuntu-24.04 和 ubuntu-24.04-arm 上的 Node 24.0.0、24.22.1 和 26.12.1 |
| macOS (x64、arm64) | macos-15-intel 上的 Node 24.0.0 和 24.22.1;macos-15 上的 Node 24.22.1;使用 Node 26.12.1 进行安装验证 |
| Windows x64 | windows-2025 上的 Node 24.0.0 和 24.22.1;使用 Node 26.12.1 进行安装验证 |
| Docker / Kubernetes | node:24-bookworm-slim、node:26-bookworm-slim、node:24-bullseye-slim,Ubuntu 22.04/24.04;只读,512 MB,x64 和 arm64(Kubernetes 清单未在 CI 中应用) |
| Google Cloud Run、Fly.io、Railway、Render、Heroku | 相同的容器镜像和 Dockerfile;这些平台本身从未被部署到 |
| AWS Lambda(容器镜像) | public.ecr.aws/lambda/nodejs:24 + 通过运行时接口模拟器(Runtime Interface Emulator)的 AWS Lambda Web Adapter,x86_64 和 arm64;amazonlinux:2023 |
AWS Lambda (.zip, nodejs24.x) |
通过 Runtime Interface Emulator 在 public.ecr.aws/lambda/nodejs:24 中运行每个服务器模板的 --target lambda zip,支持 x86_64 和 arm64,以及 API Gateway REST/HTTP、函数 URL 和 ALB 事件;sam local invoke 和 sam local start-api |
| Lambda@Edge (origin request, x86_64) | 具有 CloudFront origin-request 事件的相同镜像和模拟器 |
| Vercel Functions (Node.js 24) | vercel build 离线;位于 public.ecr.aws/lambda/nodejs:24 中 @vercel/node 下方的函数 |
| Netlify Functions (v2) | netlify build --offline 和 netlify dev --offline;位于 public.ecr.aws/lambda/nodejs:24 中的部署 zip |
| Azure Functions (Node.js v4 model, Linux) | Azure Functions Core Tools func start |
Google Cloud Functions (gen2, nodejs24) |
Ubuntu 24.04 上的 Functions Framework;Google Cloud 的 buildpacks 镜像 |
| Alpine/musl 容器 | node:24-alpine、node:26-alpine,x64 和 arm64,只读,512 MB |
| DigitalOcean App Platform (gVisor) | gVisor runsc 下的容器镜像,x64 |
| Cloudflare Workers (0.2.0) | wrangler dev 4.152.0 (workerd),带有 Free 计划的预算限制 |
| Vercel Edge (0.2.0) | vercel build 离线且 Vercel 的 edge-runtime |
| Netlify Edge (0.2.0) | netlify build --offline 和 netlify dev --offline |
| Deno Deploy (0.2.0) | 运行 deno/main.mjs 的 Deno 2.9.6 |
| Supabase Edge Functions (0.2.0) | Docker 中的 Supabase edge-runtime v1.77.8 镜像 |
| Bun 和 Deno 程序 (0.2.0) | 所有五个平台上的 Bun 1.4.4 和 Deno 2.9.6 |
| WASI, wasi-http, Spin, Fastly (0.3.0) | wasmtime 49.0.4 (run, serve), wasmer 7.4.2, Node 的 node:wasi, Spin 4.2.2, Viceroy 0.21.1 (wasi.yml) |
| 浏览器 (0.3.0) | Playwright 1.63.0:ubuntu-24.04 上的 Chromium 153 和 Firefox 155;ubuntu-24.04 和 macos-15 上的 WebKit 26.6 (browser.yml) |
在 Windows 上构建并复制到 Linux(非通过 docker build 复制)的 dist/ 需要 chmod 755 dist/host/native/process/linux-*。Node 的 --jitless 无法工作(它会禁用 WebAssembly)。限制虚拟内存的主机(ulimit -v、vm.overcommit_memory=2)会拒绝需要预留约 22 GB 地址空间的 Node 构建。Node 26 的官方二进制文件在自行安装 tarball 的极简镜像上需要 libatomic1。
Lean 支持与限制
构建强制执行提前(ahead-of-time)执行。 支持普通函数、递归、闭包、归纳类型、模式匹配、类型类、依赖类型和编译后的 IO。导入、宏、 elaboration、tactic、deriving、证明和 #eval 在托管的 native Lean 中在编译期间运行。初始化程序算作运行时依赖项:宽泛的 import Lean 可能会保留编译器;当只有宏或 tactic 需要它时使用 meta import Lean,对于运行时数据库则使用更窄的导入(具有 Lean.Json 的 import Lean,以及 deriving ToJson, FromJson,构建并运行)。每一次拒绝都会有解释:Lasm 会打印从你的代码到编译器代码的链,当起因是宽泛的导入时,还会打印你的代码所使用的更窄的模块。部署的程序会像 native Lean 一样遵循 LEAN_ABORT_ON_NONLINEAR=1。各平台结果:language coverage。
部署的应用程序不能使用:
| 运行时不可用 | 示例与确切边界 |
|---|---|
| 加载 Lean 模块数据或定位编译器安装 | Lean.importModules、Lean.withImportModules、模块数据读写器、Lean.findSysroot、Lean.initSearchPath;已部署的 .olean/IR 加载。 |
| 求值或编译新的 Lean 代码 | Lean.Environment.evalConst、解释器求值、Lean REPL、运行时 elaboration/编译、按名称加载的声明求值。允许调用普通的已编译函数。 |
| 使用 Lean 的编译器/内核运行时状态 | 运行时 elaboration、内核证明检查、编译器环境、需要 Lean C++ 编译器/内核的语言服务器机制。如果纯 Lean 数据的可达依赖项通过检查,则允许进行纯 Lean 数据操作。LeanExport.parseStream 通过内核构建 Lean.Expr 值,因此会被拒绝。 |
| 动态加载可执行插件 | Lean/Wasm 插件加载、dlopen/dlsym(调用 dlopen 的 C 代码会获得一个总是失败的实现)、运行时 Lean 符号查找。 |
构建会检查可达的运行时依赖项,包括导入的库和间接调用;即使您的输入不会走该分支,可达的禁用调用也会被拒绝,并且链接器移除的死代码不计入内。在加载应用程序之前,启动程序还会拒绝丢失、陈旧或不兼容的功能记录(这是一个一致性检查,而不是安全沙箱)。不存在庞大的兼容性回退机制。
Lake 包。仅为编译而导入的模块(例如用于宏的战术、细化器,例如 Aesop、Qq 或 import Lean)不会将 Lean 编译器留在部署中。Lasm 仅在程序使用其定义或注册的内容时,或者当它们是程序自身编写的代码执行 IO 或调用 C 时(--verbose 显示了跳过了多少个),才会运行模块的初始化程序。包捆绑的 C 源代码(extern_lib、moreLinkObjs,例如 leansqlite 的 SQLite)使用 Lean 自己的 clang 进行编译,作为 C 层获取一次(39–52 MB);不需要系统的 C 编译器(macOS 需要用于 C 库头文件的 Xcode Command Line Tools SDK)。无法链接预构建的原生库(共享库、-l 选项:libcurl、OpenSSL、libpq、BLAS);构建会指明库和包的名称。
非发布保证。控制台输出、参数、退出码、本地 Lake 导入以及选定的语言/文件系统测试拥有原生与 Node 的对比测试,并且在 0.1.0 之前,Lean 具备运行时能力的上游套件和 19 个生态系统项目在所有五个平台上运行,与上一个接受的候选版本相比零回归(0.1.0 门禁)。不保证完整的 IO.FS、并发性、子进程/信号/终端奇偶校验、每个第三方库以及完整的主流套件(IO 差距)。大数字(超出 63 位的 Nat/Int)使用 Lean 自己的任意精度代码来代替 GNU MP,因此应用不包含 LGPL 代码;结果与原生 Lean 相同,但在 Wasm 中,在 1,000 位时,乘法比使用 GMP 慢约 5 倍,Nat.gcd 慢约 60 倍(数字)。Lake 依赖项使用您的系统 Git(系统 Git)。
发布版本与来源
0.1.0 是第一个 npm 版本(说明);0.2.0 添加了边缘目标和 Bun/Deno(说明);0.3.0 添加了浏览器、Lasm.UI、全栈应用、WASI/Fastly 和编辑器支持(说明);0.3.1 将启动代码置于 MIT-0 许可证下并添加了错误报告指针(说明);0.3.2 修复了 Std.Internal.UV 套接字、定时器和信号(说明);0.3.3 从未发布,其更改随 0.3.4 发布(说明);0.3.5 更新了 README 和 Conduit 示例(说明)。Lasm 的 npm 包(@lasm/cli、@lasm/create 和 @lasm/… 工具包)仅通过 release.yml 工作流发布,通过带有来源证明的 npm 可信发布:不存在 npm 令牌。一个发布版本是一个提升 package.json 版本的拉取请求(pull request),并且只有在发布提交的 release-checks 状态(五平台候选检查;边缘、Bun/Deno、浏览器、Lasm.UI、WASI/Fastly、全栈、单元和开发循环检查;以及确切包的 npm 排练)通过后才会发布。发现了 Bug?npx lasm --version 提供了bug 报告表单所要求的版本行。npm view @lasm/cli@<version> 显示了来源证明,项目中的 npm audit signatures 可以对其进行验证。详情:RELEASING.md。
许可协议
Lasm 的源码采用 MIT License(版权所有 Jordan Last)。
初始代码——在新建项目中放入的一切 lasm init 和 npm create @lasm、templates/、examples/,以及本 README 和 docs/ 中的代码示例——在所有版本中同样采用 MIT No Attribution (MIT-0):它们完全归你所有,无需署名。@lasm/create 采用 MIT,并且 @lasm/cli 的 license 字段是 Lasm 的 MIT、MIT-0 及其打包的所有组件的 SPDX 表达式,其文本位于 licenses/ 中。许可证审计列出了每个发布的组件、其许可证以及各项义务的履行方式。
- 构建
dist/。THIRD_PARTY_NOTICES.txt以 Lasm 的 MIT 声明以及 Lasm 修改的 Lean 文件列表开头,随后是构建所包含内容的许可证:Lean 的运行时与标准库(Apache-2.0)、Emscripten(MIT OR NCSA)、musl、LLVM libc++、libc++abi、libunwind 和 compiler-rt、mimalloc、libuv、koffi 以及 Lasm 的宿主(MIT)。应用不包含任何 copyleft 代码。licenses/<package>/保存了编译进program.wasm的所有 Lake 依赖项的许可证文件;通过 npm 互操作,node_modules/保存了带有各自许可证的每个软件包。当你分发dist/时,请保留这些文件。 - Edge、浏览器、WASI、Fastly 和 wasi-http 输出采用相同的声明,经自动重写以说明其文件包含的内容:每个输出目录中的一个
THIRD_PARTY_NOTICES.txt、平台捆绑的 JavaScript 上的简短/*! … */许可证横幅(edge 胶水代码、浏览器加载器)、位于服务器端输出的 Wasm 内部的完整声明文件(一个lasm.notices自定义节,因此它会随每次部署一起传输)、Fastly 软件包中的文件,以及 Vite 构建中的THIRD_PARTY_NOTICES.lasm.txt。这对你的应用意味着什么:docs/LICENSING.md。 - 工具包与发布归档。每个
@lasm/…工具包都包含一个 SPDXlicense字段和归档的许可证文件。Lean 归档包含的 (L)GPL 部分(GNU MP、GNU C 库、GCC 运行时库、Linux UAPI 头文件、MinGW-w64)以及 Lean 自身源码的具体来源,均作为发布它们的发行版的资产进行镜像(lean-4.35.0-tiers-v2)。 Lasm 不发布任何 Git 和 Apple SDK 文件。 - Lean 名称和标志是 Lean FRO 的商标。Lasm 与 Lean FRO 无隶属关系,亦未经其背书。
来源:Hacker News-首页 · github.com