Skip to main content

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

可选依赖:mcli 是通用构建工具,不强制绑定 MCLang 编译器。仅当项目需要将 Python 编译为 C++ 时,才需要安装 mcc

pip install "mclang-cli[mcc]"

安装故障排除

若曾用开发模式安装过 mcc(例如在 mcc 源码目录执行过 pip install -e .),当前环境里可能残留无 RECORD 的 mclang-compiler 安装,导致后续无法正常卸载或升级,并出现 Cannot uninstall mclang-compiler None (no RECORD file)

建议

  1. 先不卸载,直接覆盖安装(推荐):
    pip3 install --ignore-installed --no-deps mclang-compiler --break-system-packages
    
  2. 若仍异常,可手动删除后再装:用 pip3 show mclang-compiler --break-system-packages 查看 Location,在该路径的 site-packages 下删除 mclang_compiler*mcc* 相关目录,再执行 pip3 install "mclang-cli[mcc]" --break-system-packages

🔧 使用方法

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_headersvisible

顶层 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 依赖 libBlibA 又对 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、镜像私服、个人实验都得改源码。

默认 userstage 联动(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 > env MCLI_DEFAULT_STAGE > 内置 dev
  • user:CLI --user > env MCLI_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/ 存放项目模板文件

📚 文档

🔌 依赖关系

mcli 依赖于以下组件:

  • conan: C++ 包管理器(>= 2.0.0)
  • meson / ninja: 构建系统支持

可选依赖:

  • mclang-compiler (mcc extra): Python -> C++ 编译器,仅 MCLang 项目需要(pip install "mclang-cli[mcc]"

构建系统: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

mclang_cli-0.1.19.tar.gz (189.7 kB view details)

Uploaded Source

Built Distribution

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

mclang_cli-0.1.19-py3-none-any.whl (232.9 kB view details)

Uploaded Python 3

File details

Details for the file mclang_cli-0.1.19.tar.gz.

File metadata

  • Download URL: mclang_cli-0.1.19.tar.gz
  • Upload date:
  • Size: 189.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for mclang_cli-0.1.19.tar.gz
Algorithm Hash digest
SHA256 a5b2c9caa99f59484495d3545bd2ebbb05bd60cbdfa127b3b379e8991b2f7b16
MD5 30a67dc0bfb9527ce3f4d384517cd8d2
BLAKE2b-256 731421826cee126883f9a6d5f344ef21aed07bfc1bdbc1ed45e077e57206da74

See more details on using hashes here.

File details

Details for the file mclang_cli-0.1.19-py3-none-any.whl.

File metadata

  • Download URL: mclang_cli-0.1.19-py3-none-any.whl
  • Upload date:
  • Size: 232.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for mclang_cli-0.1.19-py3-none-any.whl
Algorithm Hash digest
SHA256 0f675b63311258923cd2202f0307c8635f93b1751c73e6d824e4a4a110001355
MD5 26c40f87be0afb93ab343ff20c40d869
BLAKE2b-256 7a3f4f04cdb93e2f468b3f13853230a0875e78a9db0261317c322d94593648b5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page