modify: 0.3.4
This commit is contained in:
@@ -36,6 +36,10 @@ uv run gen_models workers/myplugin/config/workers/myplugin workers/myplugin/work
|
|||||||
- `--encrypt`:打开加密与混淆 —— `.mbank` 加密存字节码并写 `.key` 密钥文件、做 PyArmor 混淆
|
- `--encrypt`:打开加密与混淆 —— `.mbank` 加密存字节码并写 `.key` 密钥文件、做 PyArmor 混淆
|
||||||
- `--license`:打开授权 —— 注入厂商授权公钥(缺公钥则构建失败)、跑授权私钥泄漏守卫
|
- `--license`:打开授权 —— 注入厂商授权公钥(缺公钥则构建失败)、跑授权私钥泄漏守卫
|
||||||
|
|
||||||
|
打包收集清单分两处:网关本体依赖在根 `config.toml` `[pyinstaller_build_import]`;
|
||||||
|
内置插件专属依赖(网关本体不 import、只在插件里用)在根目录 `plugins_deps.toml`
|
||||||
|
(按插件分节,可选文件),`pack` 时自动并入 `--hidden-import` / `--include-module`。
|
||||||
|
|
||||||
## 项目根目录定位
|
## 项目根目录定位
|
||||||
|
|
||||||
脚本需要在项目根目录下读写 `config/`、`src/plugins/`、`workers/` 等路径。
|
脚本需要在项目根目录下读写 `config/`、`src/plugins/`、`workers/` 等路径。
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ requires = ["hatchling"]
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "chongming-cli"
|
name = "chongming-cli"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
description = "chongming 命令脚本集合:构建打包 / 进程插件打包 / 插件脚手架 / 模型生成 / 机器码授权签发"
|
description = "chongming 命令脚本集合:构建打包 / 进程插件打包 / 插件脚手架 / 模型生成 / 机器码授权签发"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
+82
-10
@@ -35,6 +35,13 @@
|
|||||||
uv run build nuitka --only mbank,prepare
|
uv run build nuitka --only mbank,prepare
|
||||||
uv run build --encrypt --license # 对外分发:加密模块 + 注入授权公钥
|
uv run build --encrypt --license # 对外分发:加密模块 + 注入授权公钥
|
||||||
uv run build # 内部调试:明文模块、不带授权
|
uv run build # 内部调试:明文模块、不带授权
|
||||||
|
|
||||||
|
依赖收集(--only pack 生效):
|
||||||
|
打包收集清单 = 根 config.toml [pyinstaller_build_import](网关本体依赖)
|
||||||
|
+ 根目录 plugins_deps.toml(内置插件专属依赖 —— 网关本体不 import、只在
|
||||||
|
mbank 内 import 的包,按插件分节声明;文件可选)。
|
||||||
|
mbank 里的 import 静态分析看不到,两条清单都会被展开为 --hidden-import /
|
||||||
|
--include-module,缺一个都会在运行期加载插件时才 ImportError。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -45,6 +52,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
import tomllib
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -54,6 +62,8 @@ from sqlite_vfs.core import SQLiteVFS
|
|||||||
from sqlite_vfs.folder_packer import FolderPacker
|
from sqlite_vfs.folder_packer import FolderPacker
|
||||||
from chongming_config import get_config, Config
|
from chongming_config import get_config, Config
|
||||||
|
|
||||||
|
from ._root import find_project_root
|
||||||
|
|
||||||
# ── 常量 ────────────────────────────────────────────────────────────────────
|
# ── 常量 ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
PYINSTALLER = "pyinstaller"
|
PYINSTALLER = "pyinstaller"
|
||||||
@@ -65,6 +75,12 @@ STEPS = ("mbank", "prepare", "obfuscate", "pack", "clean", "license_guard", "vue
|
|||||||
|
|
||||||
is_windows = platform.system() == "Windows"
|
is_windows = platform.system() == "Windows"
|
||||||
|
|
||||||
|
# 插件专属依赖清单(项目根,可选文件):内置插件(src/plugins/*)专属、网关本体
|
||||||
|
# (src/chongming/)不 import 的第三方依赖,按插件分节声明。放在插件自己的清单里
|
||||||
|
# 而不是 config.toml [pyinstaller_build_import],避免插件依赖混进网关构建配置:
|
||||||
|
# 插件下线/改 external 进程插件时删掉对应节即可,网关配置不受影响。
|
||||||
|
PLUGIN_DEPS_FILE = "plugins_deps.toml"
|
||||||
|
|
||||||
# ── 构建结果数据结构 ─────────────────────────────────────────────────────────
|
# ── 构建结果数据结构 ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
@@ -517,16 +533,73 @@ def _stage_pyarmor_obfuscate() -> str:
|
|||||||
return "✅ 所有文件混淆成功"
|
return "✅ 所有文件混淆成功"
|
||||||
|
|
||||||
|
|
||||||
|
# ── 打包收集清单(网关本体依赖 + 插件专属依赖) ─────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _load_plugin_imports() -> tuple[list[str], str]:
|
||||||
|
"""读取插件专属依赖清单(项目根 plugins_deps.toml,可选),返回 (模块列表, 摘要)。
|
||||||
|
|
||||||
|
文件结构(节名 = src/plugins/ 下的插件名):
|
||||||
|
|
||||||
|
imports = ["httpx"] # 多个插件共用的插件专属依赖
|
||||||
|
[doubao]
|
||||||
|
imports = ["openai", ...] # 单插件专属
|
||||||
|
|
||||||
|
文件不存在 = 无插件专属依赖(其他项目复用本 CLI 时不受影响),返回 ([], "")。
|
||||||
|
配置写错(imports 不是字符串列表、顶层出现非表非 imports 的键)直接抛错:
|
||||||
|
漏收依赖打包期不报错、运行期加载插件才 ImportError,静默放过的排查成本高得多。
|
||||||
|
"""
|
||||||
|
path = find_project_root() / PLUGIN_DEPS_FILE
|
||||||
|
if not path.exists():
|
||||||
|
return [], ""
|
||||||
|
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
data = tomllib.load(f)
|
||||||
|
|
||||||
|
modules: list[str] = []
|
||||||
|
notes: list[str] = []
|
||||||
|
|
||||||
|
def collect(section: str, entry) -> None:
|
||||||
|
if not isinstance(entry, list) or not all(isinstance(m, str) for m in entry):
|
||||||
|
raise ValueError(
|
||||||
|
f"{PLUGIN_DEPS_FILE} 的 [{section}] imports 必须是字符串列表"
|
||||||
|
)
|
||||||
|
modules.extend(entry)
|
||||||
|
if entry:
|
||||||
|
notes.append(f"{section}:{len(entry)}")
|
||||||
|
|
||||||
|
for name, value in data.items():
|
||||||
|
if name == "imports":
|
||||||
|
collect("共用", value)
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
collect(name, value.get("imports"))
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"{PLUGIN_DEPS_FILE} 顶层 [{name}] 只能是共用 imports 列表或 [插件名] 表"
|
||||||
|
)
|
||||||
|
return modules, "、".join(notes)
|
||||||
|
|
||||||
|
|
||||||
|
def _collect_build_imports(config: Config) -> tuple[list[str], str]:
|
||||||
|
"""打包收集清单 = 网关本体依赖(config.toml)+ 插件专属依赖(plugins_deps.toml)。
|
||||||
|
|
||||||
|
去重且保持顺序(网关本体在前);摘要空串 = 未声明插件专属依赖。
|
||||||
|
"""
|
||||||
|
base = config.get("pyinstaller_build_import", {})
|
||||||
|
items = list(base.get("base", []))
|
||||||
|
items.extend(base.get("windows", []) if is_windows else base.get("linux", []))
|
||||||
|
plugin_items, summary = _load_plugin_imports()
|
||||||
|
return list(dict.fromkeys([*items, *plugin_items])), summary
|
||||||
|
|
||||||
|
|
||||||
# ── 阶段 4: PyInstaller 打包 ────────────────────────────────────────────────
|
# ── 阶段 4: PyInstaller 打包 ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def _stage_pyinstaller(config: Config) -> tuple[str, str]:
|
def _stage_pyinstaller(config: Config) -> tuple[str, str]:
|
||||||
"""执行 PyInstaller 打包,返回 (状态消息, 可执行文件路径)"""
|
"""执行 PyInstaller 打包,返回 (状态消息, 可执行文件路径)"""
|
||||||
base_imports = config.get("pyinstaller_build_import", {})
|
build_imports, plugin_summary = _collect_build_imports(config)
|
||||||
build_imports = list(base_imports.get("base", []))
|
if plugin_summary:
|
||||||
build_imports.extend(
|
print(f" 📎 并入插件专属依赖 {PLUGIN_DEPS_FILE}({plugin_summary})")
|
||||||
base_imports.get("windows", []) if is_windows else base_imports.get("linux", [])
|
|
||||||
)
|
|
||||||
|
|
||||||
icon = Path("../../public/chongming.ico")
|
icon = Path("../../public/chongming.ico")
|
||||||
cmd = [
|
cmd = [
|
||||||
@@ -581,10 +654,9 @@ def _stage_pyinstaller(config: Config) -> tuple[str, str]:
|
|||||||
|
|
||||||
def _stage_nuitka(config: Config) -> tuple[str, str]:
|
def _stage_nuitka(config: Config) -> tuple[str, str]:
|
||||||
"""执行 Nuitka 打包,返回 (状态消息, 可执行文件路径)"""
|
"""执行 Nuitka 打包,返回 (状态消息, 可执行文件路径)"""
|
||||||
base_imports = config.get("pyinstaller_build_import", {}).get("base", [])
|
build_imports, plugin_summary = _collect_build_imports(config)
|
||||||
extra = config.get("pyinstaller_build_import", {}).get(
|
if plugin_summary:
|
||||||
"windows" if is_windows else "linux", []
|
print(f" 📎 并入插件专属依赖 {PLUGIN_DEPS_FILE}({plugin_summary})")
|
||||||
)
|
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
sys.executable,
|
sys.executable,
|
||||||
@@ -609,7 +681,7 @@ def _stage_nuitka(config: Config) -> tuple[str, str]:
|
|||||||
if shutil.which("upx"):
|
if shutil.which("upx"):
|
||||||
cmd.append("--enable-plugin=upx")
|
cmd.append("--enable-plugin=upx")
|
||||||
|
|
||||||
for mod in list(base_imports) + extra:
|
for mod in build_imports:
|
||||||
cmd.append(f"--include-module={mod}")
|
cmd.append(f"--include-module={mod}")
|
||||||
|
|
||||||
if is_windows:
|
if is_windows:
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chongming-cli"
|
name = "chongming-cli"
|
||||||
version = "0.3.2"
|
version = "0.3.4"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "chongming-config" },
|
{ name = "chongming-config" },
|
||||||
|
|||||||
Reference in New Issue
Block a user