Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions tools/build_plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""Print a non-invasive mcoplib build plan as JSON."""

from __future__ import annotations

import argparse
import json
import os
import shutil
from pathlib import Path


SUBMODULE_FLAGS = [
"BUILD_VLLM_SUBMODULE",
"BUILD_SGLANG_SUBMODULE",
"BUILD_LMDEPLOY_SUBMODULE",
"BUILD_DEFAULT_OP_SUBMODULE",
"BUILD_MOE_SUBMODULE",
"BUILD_SGL_KERNEL_SUBMODULE",
"BUILD_SGL_GROUPED_GEMM_SUBMODULE",
"BUILD_SGL_MOE_W4A16_SUBMODULE",
]
Comment on lines +13 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

CMakeLists.txt 中,BUILD_VLLM_SUBMODULEBUILD_SGLANG_SUBMODULE 是两个非常关键的子模块构建选项(分别在第 135 行和第 136 行定义)。然而,它们在 SUBMODULE_FLAGS 列表中被遗漏了。

建议将它们加入到 SUBMODULE_FLAGS 中,以确保构建计划输出的完整性。

Suggested change
SUBMODULE_FLAGS = [
"BUILD_LMDEPLOY_SUBMODULE",
"BUILD_DEFAULT_OP_SUBMODULE",
"BUILD_MOE_SUBMODULE",
"BUILD_SGL_KERNEL_SUBMODULE",
"BUILD_SGL_GROUPED_GEMM_SUBMODULE",
"BUILD_SGL_MOE_W4A16_SUBMODULE",
]
SUBMODULE_FLAGS = [
"BUILD_VLLM_SUBMODULE",
"BUILD_SGLANG_SUBMODULE",
"BUILD_LMDEPLOY_SUBMODULE",
"BUILD_DEFAULT_OP_SUBMODULE",
"BUILD_MOE_SUBMODULE",
"BUILD_SGL_KERNEL_SUBMODULE",
"BUILD_SGL_GROUPED_GEMM_SUBMODULE",
"BUILD_SGL_MOE_W4A16_SUBMODULE",
]



def read_maca_version(maca_path: str | None) -> str | None:
if not maca_path:
return None
version_file = Path(maca_path) / "Version.txt"
if not version_file.is_file():
return None
lines = version_file.read_text(encoding="utf-8").splitlines()
return lines[0].split(":")[-1].strip() if lines else None


def build_plan(root: Path) -> dict[str, object]:
maca_path = os.environ.get("MACA_PATH")
return {
"root": str(root),
"maca_path": maca_path,
"maca_version": read_maca_version(maca_path),
"tools": {
"cmake_maca": shutil.which("cmake_maca"),
"make_maca": shutil.which("make_maca"),
"mxcc": shutil.which("mxcc"),
"ninja": shutil.which("ninja"),
},
"submodules": {flag: os.environ.get(flag, "ON") for flag in SUBMODULE_FLAGS},
"cache": {
"FETCHCONTENT_BASE_DIR": os.environ.get(
"FETCHCONTENT_BASE_DIR", str(root / ".deps")
)
},
}


def main() -> int:
parser = argparse.ArgumentParser(description="Print mcoplib build plan JSON.")
parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1])
parser.add_argument("--output", type=Path)
args = parser.parse_args()

text = json.dumps(build_plan(args.root.resolve()), indent=2, sort_keys=True)
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(text + "\n", encoding="utf-8")
else:
print(text)
return 0


if __name__ == "__main__":
raise SystemExit(main())
40 changes: 40 additions & 0 deletions unit_test/test_build_plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import os
import tempfile
import unittest
from pathlib import Path

import sys

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from tools.build_plan import build_plan, read_maca_version


class BuildPlanTest(unittest.TestCase):
def test_read_maca_version(self):
with tempfile.TemporaryDirectory() as tmp:
Path(tmp, "Version.txt").write_text("Version:3.5.3.20\n", encoding="utf-8")
self.assertEqual(read_maca_version(tmp), "3.5.3.20")
Comment on lines +14 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议为 read_maca_version 增加针对空文件以及无冒号格式等边界情况的单元测试,以确保版本解析逻辑在各种异常输入下都能正确、安全地运行。

Suggested change
def test_read_maca_version(self):
with tempfile.TemporaryDirectory() as tmp:
Path(tmp, "Version.txt").write_text("Version:3.5.3.20\n", encoding="utf-8")
self.assertEqual(read_maca_version(tmp), "3.5.3.20")
def test_read_maca_version(self):
with tempfile.TemporaryDirectory() as tmp:
# 测试正常情况
Path(tmp, "Version.txt").write_text("Version:3.5.3.20\\n", encoding="utf-8")
self.assertEqual(read_maca_version(tmp), "3.5.3.20")
# 测试空文件情况
Path(tmp, "Version.txt").write_text("", encoding="utf-8")
self.assertIsNone(read_maca_version(tmp))
# 测试无冒号情况
Path(tmp, "Version.txt").write_text("Version3.5.3.20\\n", encoding="utf-8")
self.assertEqual(read_maca_version(tmp), "Version3.5.3.20")


Path(tmp, "Version.txt").write_text("", encoding="utf-8")
self.assertIsNone(read_maca_version(tmp))

Path(tmp, "Version.txt").write_text("Version3.5.3.20\n", encoding="utf-8")
self.assertEqual(read_maca_version(tmp), "Version3.5.3.20")

def test_build_plan_uses_default_submodule_flags(self):
root = Path.cwd()
old = os.environ.pop("BUILD_DEFAULT_OP_SUBMODULE", None)
try:
plan = build_plan(root)
finally:
if old is not None:
os.environ["BUILD_DEFAULT_OP_SUBMODULE"] = old

self.assertEqual(plan["submodules"]["BUILD_DEFAULT_OP_SUBMODULE"], "ON")
self.assertEqual(plan["submodules"]["BUILD_VLLM_SUBMODULE"], "ON")
self.assertEqual(plan["submodules"]["BUILD_SGLANG_SUBMODULE"], "ON")


if __name__ == "__main__":
unittest.main()