Skip to main content

infinity_make

PyPI - Version PyPI - Python

基于 InfinityData.infd 声明式配置语言)的自定义构建系统。

infmake.infd 是一棵操作树:每个节点是一个带内嵌 Python 实现的模板实例。编译 .infd → 执行操作树 → 输出物化 JSON 产物,全程带子图去重、VFS 注入与持久化节点缓存。

uv run infmake -i infmake.infd --dev -o make_result.json

特性

  • 操作树构建.infd 声明构建流程,节点 = 模板 + 数据字段 + 内嵌 impl(Python)
  • 子图 hash 去重:相同(模板 + 实现 + 物化输入)的子图只求值一次,结果复用
  • 持久化节点缓存:节点物化结果按 hash 落盘(<workspace>/node_cache/<hash>.json),跨运行复用
  • VFS / id 注入impl 签名声明 vfs / id 参数即注入构建工作区与节点标识(临时目录 + 按 key 缓存 / NodeId 指纹)
  • Nix 环境引导env.infd → 自动 nix develop 重入构建(flake / impure 两种模式)
  • 沙盒安全:默认零信任 deny_all()--dev 开发模式 full_access()!from / !file / !env 全开)
  • 可审计产物:输出为自包含的物化 JSON 树

安装

需要 Python ≥ 3.12。包已发布到 PyPI(包名 infinity_make)。

# 作为项目依赖(从 PyPI 安装)
uv add infinity_make

# 或用 pip
pip install infinity_make

# 本地开发(本仓库内)
uv sync
uv run infmake --help

安装后提供 infmake 命令(python -m infinity_make 亦可)。

快速开始

一个最小示例,三件套:模板文件 → 构建配置 → 运行。

1. 模板 templates/hello.inft.inft = 仅模板定义的源文件):

~Hello {
    name: str = "world"

    _gen: dict = {
        message: str = ""
    }
    _impl: str = ```python
def impl(name: str) -> dict[str, str]:
    return {"message": f"hello, {name}!"}
    ```
}
  • _gen:声明 impl 产出的字段(元数据,不进物化记录)
  • _impl:内嵌 Python 源码(三重反引号多行字符串),约定定义名为 impl 的函数
  • impl 收到的参数是降维后的普通 Python 值str / int / list / dict / PurePosixPath),返回的 dict 合并回节点记录

2. 构建配置 infmake.infd

!from p"templates/hello.inft" import Hello

!var Hello(name = "world") import . as hello

target = $hello
  • !from ... import:导入模板
  • !var ... import . as ...:定义变量(节点实例)
  • target:顶层入口字段,即操作树根

3. 运行

uv run infmake -i infmake.infd --dev -o make_result.json

产物 make_result.json

{
  "name": "world",
  "message": "hello, world!"
}

使用了 !from / !file / !env 的配置必须加 --dev(默认沙盒为零信任 deny_all(),禁止导入)。

命令行

usage: infmake [-h] [-i INPUT] [-o OUTPUT] [-e ENV] [-w WORKSPACE] [--dev] [--run CMD]

options:
  -h, --help            显示帮助
  -i, --input INPUT     构建配置(默认 infmake.infd)
  -o, --output OUTPUT   构建结果位置(默认 make_result.json)
  -e, --env ENV         Nix 环境声明文件(默认 <input> 同目录 env.infd)
  -w, --workspace WORKSPACE
                        VFS 工作区目录(默认 <input> 同目录 .builder)
  --dev                 开发模式沙盒(full_access:!from / !file / !env 全开)
  --run CMD             进入 env.infd 的 Nix 环境运行命令(不构建),如 --run "code ."

执行流程:加载 env.infd(存在则引导 Nix 环境重入)→ 编译 infmake.infd → 执行操作树 → 输出物化 JSON。

Nix 环境(env.infd)

infmake.infd 同目录放置 env.infd(纯数据,经包内 schemas/env.inftEnvSpec 模板严格校验)后,构建会自动 nix develop 重入,环境内 !env import 可用:

packages = [
    "clang",
    "cmake",
    "ninja",
]

env = {
    CMAKE_PREFIX_PATH = "${cmake}",
}

shell_hook = ```bash
export NIX_HARDENING_ENABLE="pic relro"

flake = { inputs = { nixpkgs = "github:nixos/nixpkgs/nixos-26.05" } }

clone = [ { url = "https://github.com/foo/bar.git" dest = p"deps/bar" tag = "v1.2.3" } { url = "git@github.com:foo/baz.git" dest = p"src/baz" commit = "3f2a1c9d8b7e" } ]


- `packages`:Nix 包列表
- `env`:环境变量,`${attr}` 自动展开为 nix 字符串插值 `${pkgs.attr}`
- `shell_hook`:进入环境后、构建前执行的 bash(再 `exec` 构建)
- `flake = {...}`:显式启用 **flake 模式**(自动生成 `flake.nix` + `flake.lock`,commit 级锁定 nixpkgs);缺省 = impure `nix develop --expr`
- `clone`:可选;**git 项目克隆声明**,在构建/进入环境前把项目克隆到指定位置(相对 `env.infd` 所在目录)。每项必须**锁 tag 或 commit(二选一)**,克隆后校验 `HEAD == 锁定提交` 保证可复现:
  - `url`:git 仓库地址(必填)
  - `dest`:目标目录(`p"..."` 路径字面量)
  - `tag`:锁定 tag
  - `commit`:锁定 commit(非分支/标签顶端的提交也会显式拉取)
  - 幂等:目标已存在且是 git 仓库时收敛远端并拉取、检出锁定;已存在但非 git 仓库则报错不覆盖

重入通过环境变量 `INFMAKE_NIX_ENV`(= env.infd 语法层指纹)防死循环;`env.infd` 内容变化才触发重建。

`--run` 可只进入该环境运行命令而不构建:

```bash
uv run infmake --run "code ."        # 在 Nix 环境里打开 VS Code
uv run infmake --run "bash gen_pkgconfig.sh"

进阶用法

模板与实现外置

实现代码可外置到 .py 文件,用 !file ... as raw 导入为字符串(模板内再引用):

# core.inft
!file p"impl/compile.py" as raw import . as CompileImpl

~Compile {
    compiler: Compiler
    source: File
    flags: <list, each(str)> = []
    _gen: dict = {
        object: str = "",
        compile_command: object = {},
    }
    _impl: str = $CompileImpl
}
# impl/compile.py
def impl(compiler: dict, source: dict, flags: list[str], vfs) -> dict:
    ...
    return {"object": obj, "compile_command": cmd}

内容快照节点(~File)

path 类型的字段(p"src")由 impl 收到 PurePosixPath;若要文件内容参与节点 hash(内容变化 → 下游缓存自动失效),用 ~File 节点对文件/目录算内容指纹,下游 $file 引用它即可(指纹自动传播进下游节点 key):

~File {
    path: path
    ignore: <list, each(str)> = []
    mtime: bool = false        # mtime 快照加速
    _cache: bool = false       # 内容检测节点:每次执行重读
    _gen: dict = {
        path: str = "",
        hash: str = "",
        entries: int = 0,
        exists: bool = false,
    }
    _impl: str = ```python
def impl(path: str, ignore: list[str], mtime: bool, vfs) -> dict:
    ...   # 递归内容指纹(sha256)
    ```
}

VFS 注入

impl 签名含 vfs 参数即注入节点作用域代理(缓存自动以当前节点 hash 为 key):

def impl(tag, vfs):
    tmp = vfs.tmp("stage")            # 一次性临时目录(每次调用新建)
    cache = vfs.cache()               # → cache/<节点hash>(跨运行复用)
    shared = vfs.data("pcm")          # → data/pcm(全局持久目录,跨节点共享)
    return {"tmp_dir": str(tmp), "cache_dir": str(cache)}

节点标识(id 注入)

impl 签名含 id 参数即注入当前节点的 :class:NodeIdnode_hash / template_hash):

def impl(tag, id):
    # id.node_hash       → 完整节点指纹(模板名 + 实现源码 + 物化输入)
    # id.template_hash   → 模板 + 实现指纹(不含输入)
    ...
  • node_hash:完整节点指纹,也是持久化缓存 <node_hash>.jsonvfs.cache() 目录的 key
  • template_hash:不含输入的「模板 + 实现」指纹——同一模板实现、不同输入时 hash 相同

节点缓存

  • 默认开启:节点物化结果经 dump_to_json / load_from_json 无损往返落盘 <workspace>/node_cache/<hash>.jsonDecimal / path / noexist 以自描述标记编码)
  • 模板声明 _cache: bool = false 关闭(如 ~File 内容检测)

项目结构

src/infinity_make/
  __init__.py      公共 API(Executor / BuildError / main)
  __main__.py      python -m infinity_make 入口
  main.py          CLI 薄壳:argparse → 编译 → 执行 → 输出 JSON
  executor.py      操作树执行器(子图 hash 去重 + VFS 注入 + 节点缓存)
  nixenv.py        Nix 环境引导(env.infd → nix develop 重入 / --run)
  vfs/             构建工作区 VFS(tmp + cache + node_cache)
  schemas/env.inft env.infd 的 EnvSpec schema(包内分发)

工作区(默认 <input> 同目录 .builder/):

.builder/
  tmp/         一次性临时目录(每次构建从干净区开始,缓存保留)
  data/        全局持久目录(vfs.data(name))
  cache/       VFS 缓存(<key>,跨运行复用)
  node_cache/  节点物化缓存(<hash>.json)

开发

uv sync --group dev        # ruff / pyright / pre-commit / pytest
uv run ruff check .
uv run pyright
uv run pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infinity_make-1.1.0.tar.gz (34.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infinity_make-1.1.0-py3-none-any.whl (24.0 kB view details)

Uploaded Python 3

File details

Details for the file infinity_make-1.1.0.tar.gz.

File metadata

  • Download URL: infinity_make-1.1.0.tar.gz
  • Upload date:
  • Size: 34.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for infinity_make-1.1.0.tar.gz
Algorithm Hash digest
SHA256 f72e8ec4b25df3029c42d4972f32e8939384a21792361d3d6b28cb5554edc159
MD5 886b77db523f50b813f95a0a8c7fa57a
BLAKE2b-256 cba2aa52d7a0edf49adfb6f2fcf995f3f2b2bcd57f6166c360fb1fb892822dbf

See more details on using hashes here.

File details

Details for the file infinity_make-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: infinity_make-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 24.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for infinity_make-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 919f028ed9a25ae81c546fb6c3e366d0e04b28366608b16940bd64fe9f10ebaf
MD5 f7f7e18b7aac321741ed6dea04740171
BLAKE2b-256 00a8ef9d07c28af4eb570b5f5b8d59f10302350c5035dac4fe9e24856403b682

See more details on using hashes here.

Release history Release notifications | RSS feed

1.1.2

2 files

1.1.1

2 files

This release

1.1.0 This release

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page