LLVM 命令行处理

LLVM 命令行处理

以下是一个结合 cl::opt、cl::list、cl::sub 的 复杂命令行接口样例,模拟一个类似 git 的工具,支持子命令、多参数、标志选项和位置参数:

#include "llvm/Support/CommandLine.h"
#include <iostream>

using namespace llvm;

// --- 全局选项(所有子命令共享)---
cl::opt<bool> Verbose(
    "verbose", 
    cl::desc("Enable verbose output"),
    cl::init(false)
);

// --- 子命令 'init' ---
cl::opt<std::string> RepoName(
    "name",
    cl::desc("Repository name"),
    cl::value_desc("string"),
    cl::init("my_repo")  // 默认值
);

cl::SubCommand InitCmd("init", "Initialize a new repository");

// --- 子命令 'commit' ---
cl::list<std::string> Files(
    "files",
    cl::desc("Files to commit"),
    cl::value_desc("filename"),
    cl::ZeroOrMore,  // 允许零或多个参数
    cl::CommaSeparated  // 支持逗号分隔
);

cl::opt<std::string> Message(
    "m",
    cl::desc("Commit message"),
    cl::value_desc("string"),
    cl::Required  // 必须提供
);

cl::SubCommand CommitCmd("commit", "Commit changes");

// --- 子命令 'remote'(嵌套子命令)---
cl::SubCommand RemoteAddCmd("add", "Add a remote repository");
cl::opt<std::string> RemoteName(
    "name",
    cl::desc("Remote name"),
    cl::Required,
    cl::sub(RemoteAddCmd)  // 仅对 'remote add' 有效
);
cl::opt<std::string> RemoteUrl(
    "url",
    cl::desc("Remote URL"),
    cl::Required,
    cl::sub(RemoteAddCmd)
);

cl::SubCommand RemoteCmd("remote", "Manage remote repositories");

int main(int argc, char **argv) {
    // 设置帮助信息
    cl::ParseCommandLineOptions(argc, argv, "Git-like CLI Example\n");

    // 全局选项处理
    if (Verbose)
        errs() << "Verbose mode enabled\n";

    // 子命令分发
    if (InitCmd) {
        errs() << "Initializing repo: " << RepoName << "\n";
    } 
    else if (CommitCmd) {
        errs() << "Committing with message: " << Message << "\n";
        for (const auto &file : Files)
            errs() << " - " << file << "\n";
    } 
    else if (RemoteCmd) {
        if (RemoteAddCmd) {
            errs() << "Adding remote: " << RemoteName 
                   << " -> " << RemoteUrl << "\n";
        } else {
            errs() << "Unknown remote subcommand\n";
        }
    } 
    else {
        errs() << "No valid subcommand provided. Use --help for usage.\n";
        return 1;
    }

    return 0;
}

功能说明

1.全局选项

--verbose:所有子命令共享的调试标志。

2.子命令 init

用途:初始化仓库。
选项:

--name <string>:指定仓库名称(默认 my_repo)。

示例:

./cli init --name=my_project

3.子命令 commit

用途:提交文件变更。
选项:

--files <file1,file2>:提交的文件列表(逗号分隔或多次指定)。
-m <message>:必须提供的提交信息。

示例:

./cli commit --files=a.txt,b.txt -m "Fix bugs"
# 或
./cli commit --files a.txt --files b.txt -m "Fix bugs"

4.嵌套子命令 remote add

用途:添加远程仓库地址。
选项:

--name <string>:远程仓库名称(必须提供)。
--url <string>:远程仓库URL(必须提供)。

示例:

./cli remote add --name=origin --url=https://github.com/user/repo.git

运行示例

1. 显示帮助信息

./cli --help

# 输出:
#   USAGE: cli [options] <subcommand> [subcommand options]
#   OPTIONS:
#     --verbose     - Enable verbose output
#   SUBCOMMANDS:
#     init          - Initialize a new repository
#     commit        - Commit changes
#     remote        - Manage remote repositories

2. 初始化仓库

./cli init --name=my_project --verbose
# 输出:
#   Verbose mode enabled
#   Initializing repo: my_project

3. 提交文件

./cli commit --files=a.cpp,b.cpp -m "Add features"
# 输出:
#   Committing with message: Add features
#    - a.cpp
#    - b.cpp

4. 添加远程仓库

./cli remote add --name=origin --url=https://github.com/user/repo.git
# 输出:
#   Adding remote: origin -> https://github.com/user/repo.git

关键设计点

  • 子命令隔离
    通过 cl::sub() 将选项绑定到特定子命令,避免命名冲突。
    例如 --name 在 init 和 remote add 中含义不同。

  • 灵活的参数输入
    cl::list 支持多值输入(逗号分隔或重复选项)。
    cl::Required 强制用户提供必要参数。

  • 嵌套子命令
    类似 git remote add 的层级结构,通过嵌套 SubCommand 实现。

  • 默认值与校验
    cl::init 设置默认值,cl::value_desc 提供类型提示。

posted @ 2025-04-27 14:58  michaelchengjl  阅读(49)  评论(0)    收藏  举报