MCLang CLI - MCLang 项目管理工具
Project description
MCLang CLI - MCLang 项目管理工具
MCLang CLI (mcli) 是 MCLang 工具链的命令行项目管理工具,提供项目创建、构建、依赖管理等功能。
🚀 特性
- 项目创建: 快速创建 MCLang 项目
- 依赖管理: 基于 Conan 的 C++ 依赖管理
- 交叉编译: 以
target为中心安装和使用交叉编译目标 - 模板系统: 内置项目模板和 stub 文件生成
📦 安装
pip install mclang-cli
安装后使用 mcli 命令:
mcli --version
或从源码安装:
git clone https://gitcode.com/zjp99/mcli.git
cd mcli
pip install -e . --force-reinstall --no-deps
# 安装到全局环境
pip install -e . --break-system-packages --force-reinstall --no-deps
注意: 安装 mclang-cli 会自动安装 mclang-compiler 作为依赖。
安装故障排除
若曾用开发模式安装过 mcc(例如在 mcc 源码目录执行过 pip install -e .),当前环境里可能残留无 RECORD 的 mclang-compiler 安装,导致后续无法正常卸载或升级,并出现 Cannot uninstall mclang-compiler None (no RECORD file)。
建议:
- 先不卸载,直接覆盖安装(推荐):
pip3 install --ignore-installed --no-deps mclang-compiler --break-system-packages
- 若仍异常,可手动删除后再装:用
pip3 show mclang-compiler --break-system-packages查看Location,在该路径的site-packages下删除mclang_compiler*与mcc*相关目录,再执行pip3 install mclang-cli --break-system-packages。
全新环境仅执行 pip install mclang-cli 时,会自动从 PyPI 安装带完整元数据的 mclang-compiler,一般不会出现上述问题。
🔧 使用方法
mcli 项目管理
# 创建新项目
mcli create my-project --template lib
# 构建项目
mcli build
# 构建并运行
mcli run
# 运行测试
mcli test
# 依赖管理(使用 Conan)
conan install . --user=dev
# 发布包
mcli publish --channel stable -bt release
# 安装交叉 target(若已配置 catalog,可省略 --manifest)
mcli target add aarch64-unknown-linux-gnu --manifest ./targets/aarch64-unknown-linux-gnu.toml
# 查看 target
mcli target list
mcli target info aarch64-unknown-linux-gnu
# 按 target 构建/测试
mcli build --target aarch64-unknown-linux-gnu
mcli test --target aarch64-unknown-linux-gnu
# 迁移旧工具链
mcli migrate-toolchains --force
# 配置管理
mcli config
mcli config default_target
mcli config set default_target aarch64-unknown-linux-gnu
项目配置
项目使用 mds/service.json 进行配置:
{
"name": "my-project",
"version": "1.0.0",
"type": "library",
"author": "Your Name",
"license": "Mulan PSL v2",
"description": "Project description",
"dependencies": {
"build": [
{"conan": "boost/[>=1.87.0]"}
]
},
"mclang": {
"type": "native",
"stubs": {
"dir": "stubs",
"packages": ["mc", "gtest"]
}
}
}
依赖 options 与偏好声明
两个字段,职责分明:
| 字段 | 语义 | 对应 conan API |
|---|---|---|
顶层 default_options |
给依赖的 conan options 偏好(影响 package_id 匹配) | self.requires(ref, options={...}) |
dependencies[*].options |
self.requires 的 requires traits |
self.requires(ref, **kwargs)(如 transitive_headers、visible) |
顶层 default_options(推荐的 options 偏好表达方式)
语法与 conan 命令行 -o liblogger/*:test=True 对齐:
"default_options": {
"liblogger/*:test": {"Debug": true, "Release": false},
"libsomp/*:test": {"Debug": true, "Release": false},
"mydep/*:shared": false
}
- key 格式:
<pkg_name>/*:<option_name>或<pkg_name>:<option_name>,与 conan pattern 一致。 - value 支持两种形式:
- 常量(字符串/布尔/数字):不论 build_type,始终生效
- 条件字典
{"Debug": ..., "Release": ...}:按当前build_type挑选值;未覆盖的 build_type 视为未声明,让 conan 用该 option 的默认值(适合"本地 Debug 用 test=True 版依赖、交叉 Release 用 test=False"场景)
mcli 解析后会把这些偏好注入到对应 dependency 的 requires options,最终走 self.requires(ref, options={...}) 路径——所以它们会固化进 recipe,对下游可传递(即中间层封装能力)。
dependencies[*].options(requires traits)
只放 self.requires 的 trait kwargs,跟 conan options 解耦:
{
"conan": "mclboost/[>=0.1.0]",
"options": {
"transitive_headers": true,
"visible": true
}
}
中间层封装(减少顶层维护成本)
若 libA 依赖 libB、libA 又对 libB 有 options 偏好,请把偏好声明在 libA/service.json 的顶层 default_options 里。libA 发布后这份偏好会随 recipe 固化,下游消费 libA 的项目不需要再为 libB 重复声明。mcli 不会因为你的项目间接依赖 libB 而强制你在 service.json 里列出 libB。
依赖顺序的硬约束 ⚠️
conan 深度优先展开依赖图,同一包的 options 只在"被首次 require"时锁定一次(见 conan FAQ)。mcli 严格保持 service.json 里声明顺序生成 CONAN_REQUIRES,不做自动排序,这意味着你需要显式控制顺序:
- 被
default_options偏好覆盖到的依赖(如liblogger),若其他依赖(如libsomp)会间接 require 它,必须把它写在"可能间接引入它的包"之前。这样 conan 先 require 它,偏好才能生效。 - 如果你的项目同时依赖了一个"中间层包"(如
libmcpp,它对liblogger有封装偏好)和一个"直接有 options 的同级包"(如libsoc_adapter),把中间层包放在前面,让它先被 conan 展开,锁定它对传递依赖的偏好。
这些规则 mcli 无法自动推断(mcli 不知道各个依赖包内部会对哪些传递依赖施加偏好),所以由用户在 service.json 中显式保证。
📝 命令参考
create - 创建项目
mcli create <project-name> [options]
选项:
-t, --template TYPE 项目模板 (bin/lib, 默认: bin)
--list 列出所有可用模板
build - 构建项目
mcli build [options]
选项:
--bt, --build-type TYPE 构建类型 (debug/release, 默认: debug)
--target TARGET target 标识 (如 aarch64-unknown-linux-gnu, 用于交叉编译)
-j, --jobs NUM 并行构建任务数
-v, --verbose 详细输出
run - 构建并运行
mcli run [options] [-- <args>]
选项:
--bt, --build-type TYPE 构建类型
--target TARGET 构建 target (如 aarch64-unknown-linux-gnu)
--name TARGET_NAME 要运行的 mclang 可执行目标名称
-- 分隔符,后面传递给程序的参数
示例:
mcli run # 使用上次构建配置运行
mcli run -bt release # 指定构建参数运行
mcli run --target aarch64-unknown-linux-gnu # 先按交叉 target 构建,再运行产物
mcli run -- --arg1 --arg2 # 传递参数给程序
test - 运行测试
mcli test [test_names] [options] [-- <framework-args>]
选项:
--bt, --build-type TYPE 构建类型 (debug/release)
--target TARGET target 标识 (如 aarch64-unknown-linux-gnu)
-j, --jobs NUM 并行构建任务数
-v, --verbose mcli 详细输出(CTest -V)
-- 分隔符,后面传递给测试框架的参数
使用 -- 分隔符:
-- 之前:mcli 参数(测试名称用于 CTest -R 筛选)
-- 之后:直接转发给测试框架(绕过 argparse 识别)
示例:
mcli test # 运行所有测试
mcli test mcc_gtests # 运行指定测试
mcli test mcc_gtests mcc_pytests # 运行多个测试
mcli test mcc_pytests -- test_lambda.py # 转发参数给测试框架
mcli test mcc_pytests -- -v # pytest 详细输出
mcli test mcc_gtests -- --gtest_filter=*Arc* # GoogleTest filter
mcli test -v mcc_pytests -- -v # mcli 和 pytest 都详细输出
依赖管理
# 刷新依赖(更新 stub 文件)
mcli reload
# 刷新稳定版本依赖
mcli reload --channel stable -bt release
# 使用 Conan 安装依赖
conan install . --user=dev
# 查看已安装的包
conan list
target - Target 管理
mcli target list
mcli target info <target>
mcli target add <target> --manifest ./targets/<target>.toml
mcli target remove <target>
示例:
mcli target add aarch64-unknown-linux-gnu --manifest ./targets/aarch64-unknown-linux-gnu.toml
mcli build --target aarch64-unknown-linux-gnu
mcli test --target aarch64-unknown-linux-gnu
Target Manifest
target 是用户唯一需要理解的交叉编译安装单位。一个 target manifest 描述:
- 该平台使用哪个 compiler
- 该平台使用哪个 sysroot
- 对应的目标 triple / cflags / ldflags
mcli target add aarch64-unknown-linux-gnu --manifest ./targets/aarch64-unknown-linux-gnu.toml
示例 manifest:
[target]
name = "aarch64-unknown-linux-gnu"
platform = "linux-aarch64"
triple = "aarch64-unknown-linux-gnu"
[target.compiler]
name = "bmc-sdk-compiler"
source = "./artifacts/bmc-sdk-compiler.tar.gz"
type = "gcc"
tool_prefix = "aarch64-target-linux-gnu"
[target.sysroot]
name = "bmc-sdk-sysroot"
source = "./artifacts/bmc-sdk-sysroot.tar.gz"
只配不带(用户自行安装编译器)
当编译器已通过系统包管理器安装时,manifest 可以声明版本约束而不打包编译器:
[target]
name = "aarch64-unknown-linux-gnu"
cflags = ["-Os", "-ffunction-sections"]
ldflags = ["-Wl,--gc-sections"]
[target.compiler]
type = "gcc"
source = "system"
tool_prefix = "hcc-arm64le"
min_version = "7.0"
max_version = "8.0"
mcli 会从 PATH 中查找 hcc-arm64le-g++,校验版本是否满足约束(7.0 <= version < 8.0),版本不满足时输出警告。
若组织内已配置 catalog,mcli target add <target> 可直接省略 --manifest。
兼容迁移
旧的 toolchain / compiler / sysroot 机制已经退出主使用路径;如果本机还有历史资产,请用迁移命令一次性转成 target。
mcli migrate-toolchains --force
config - 配置管理
mcli config # 查看所有配置
mcli config <key> # 查看特定配置项
mcli config set <key> <value> # 设置配置项
示例:
mcli config set default_target aarch64-unknown-linux-gnu # 设置默认 target
mcli config default_target # 查看默认 target
publish - 发布包
mcli publish [options]
选项:
--user USER Conan 包所有者;不指定时按 stage 联动推导默认值
(stage=dev → openubmc.dev,其他 → openubmc),
可被环境变量 MCLI_DEFAULT_USER 整体覆盖;
传空串 (--user "") 表示「裸发,不带 user/channel」
--stage STAGE 发布阶段 (dev/rc/stable);与 bingo 的 --stage 对齐;
不指定时取 mcli 默认(dev,可被环境变量
MCLI_DEFAULT_STAGE 覆盖)
--channel CHANNEL --stage 的别名;二者不可同时指定
--bt, --build-type TYPE 构建类型 (debug/release)
-r, --remote REMOTE 上传到指定远端仓库(不指定则只导出到本地缓存)
--force 强制覆盖远端已存在的包
-o KEY=VALUE 透传 conan -o 选项,build/export-pkg 阶段都生效
(依赖项请用 pkg/*:opt 形式,例如 -o '*/*:enable_luajit=True')
Conan 包版本格式: {name}/{version}@{user}/{stage}(默认)
或 {name}/{version}(裸发模式)
示例:
mcli publish # 默认 stage=dev → @openubmc.dev/dev:libmcpp/1.2.73@openubmc.dev/dev
mcli publish --stage stable # 显式发到 stable → @openubmc/stable:libmcpp/1.2.73@openubmc/stable
mcli publish --stage rc # 发到 rc → @openubmc/rc
mcli publish -r openubmc_sdk # 默认 dev,并上传到指定远端
mcli publish --user openubmc --stage dev # 显式覆盖:发到 @openubmc/dev(绕过 stage 联动)
mcli publish --user myorg --stage dev # 命令行同时覆盖 user 和 stage
mcli publish --user "" # 裸发:libmcpp/1.2.73(不带 user/channel)
# 通过环境变量定制团队默认(写到 ~/.zshrc 或 CI 脚本里):
export MCLI_DEFAULT_USER=myteam # 整体覆盖默认 user(绕过 stage 联动)
export MCLI_DEFAULT_STAGE=rc # 默认 stage 改成 rc
设计原则:项目代码不绑死「会被发到哪里」 + 默认 user 跟 stage 联动
user/channel 都是发布行为的属性,不是项目代码的属性。所以
service.json 里不再支持 publish.user 这类配置 —— 否则一个项目的源码
仓库会硬编码 conan 仓库归属,团队 fork、镜像私服、个人实验都得改源码。
默认 user 与 stage 联动(CLI / env 都未指定时):
| stage | 默认 user | 含义 |
|---|---|---|
dev |
openubmc.dev |
本地/开发机构建,与 bingo conan create --user openubmc.dev 约定对齐,bingo 集成测试可直接 cache-hit mcli 发布的 binary |
rc / stable / 其他 |
openubmc |
远端 CI 出的正式产物归属 |
mcli 解析这两类元信息:
| 元信息 | 解析顺序 |
|---|---|
user |
CLI --user > env MCLI_DEFAULT_USER > 按 stage 推导 |
stage / channel |
CLI --stage/--channel > env MCLI_DEFAULT_STAGE > 内置 dev |
- 日常
mcli publish(不带任何参数)→@openubmc.dev/dev,跟 bingo 本地构建包同 ref,集成测试直接命中 - 想让远端 stable 仓库(依赖写的是
@openubmc/stable)拿到本机改动时, 显式mcli publish --stage stable(自动用@openubmc/stable,不带 .dev 后缀) - 别的团队默认 user 不是 openubmc:
export MCLI_DEFAULT_USER=myteam整体覆盖联动逻辑
解析优先级(统一两层 + stage 联动)
- stage/channel:CLI
--stage/--channel> envMCLI_DEFAULT_STAGE> 内置dev - user:CLI
--user> envMCLI_DEFAULT_USER> 按 stage 推导 (stage=dev →openubmc.dev,其他 →openubmc) - 命令行同时给出
--stage和--channel→ 报错(避免歧义) - CLI
--user ""→ 裸发模式(不带 user/channel),仅本地纯实验用
🏗️ 架构
mcli/
├── mcli/ # CLI 工具核心
│ ├── commands/ # 命令实现
│ │ ├── create.py # 项目创建
│ │ ├── build.py # 构建管理
│ │ ├── deps.py # 依赖管理
│ │ └── publish.py # 包发布
│ ├── toolchain/ # 工具链管理(内部模块)
│ │ ├── base.py # 工具链基类
│ │ ├── zig.py # Zig 工具链
│ │ ├── system.py # 系统工具链 (GCC/Clang)
│ │ └── manager.py # 工具链管理器
│ ├── package/ # 包管理(内部模块)
│ │ ├── manager.py # 包管理器
│ │ ├── conan.py # Conan 集成
│ │ └── abi.py # ABI 管理
│ ├── target/ # target 模型(主入口)
│ ├── template.py # 模板引擎(内置,支持 {{ }} 和 {% %} 语法)
│ ├── paths.py # 路径工具
│ ├── logging.py # 日志系统
│ └── config.py # 配置管理
└── templates/ # 项目模板
├── conanbase.py.mct # Conan 基类模板(自动生成到用户项目)
├── bin/ # 可执行程序模板
├── lib/ # 库项目模板
└── toolchain/ # 工具链配置模板
设计说明:
mcli/包含 CLI 的所有核心代码template.py是内置的模板引擎,支持 {{ }} 和 {% %} 语法target/是交叉编译主入口;toolchain/退回为内部兼容层templates/conanbase.py.mct是 Conan 基类模板,mcli build 时自动生成到用户项目目录- 用户项目的
conanfile.py通过from conanbase import ConanBase导入生成的基类 templates/存放项目模板文件
📚 文档
- MCLang CLI 使用指南 - 完整的命令参考和使用说明
🔌 依赖关系
mcli 依赖于以下组件:
- mclang-compiler: 编译器核心(自动安装)
- conan: C++ 包管理器(>= 2.0.0)
构建系统:mcli 使用 Conan 进行依赖管理和构建,用户可在项目的 conanfile.py 中选择具体的构建工具(CMake、Meson 等)。
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
Mulan PSL v2 - 详见 LICENSE 文件
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mclang_cli-0.1.18.tar.gz.
File metadata
- Download URL: mclang_cli-0.1.18.tar.gz
- Upload date:
- Size: 178.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91557a4c0232e66b70e7b803b90040a57f5c9bdd57255d691da8b8dfb461090c
|
|
| MD5 |
a9d8349f04a2421c26bbd5c551086f0d
|
|
| BLAKE2b-256 |
26f1691baecce7b1f9bfb8ce201aea5fd7111198887a47432aeee47a835728fe
|
File details
Details for the file mclang_cli-0.1.18-py3-none-any.whl.
File metadata
- Download URL: mclang_cli-0.1.18-py3-none-any.whl
- Upload date:
- Size: 219.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30b82072f2806423b7e89b5cfae691eb3c7adb2de79dfb7f6e996db167721834
|
|
| MD5 |
c8d1e67618942314d7b192beaaec5e13
|
|
| BLAKE2b-256 |
ab867f87b1db39ed60291abde3c6be6926bcab2b050afdf31e25fb63274a9b08
|