Skip to main content
Glama
install_esp_idf.py12.6 kB
#!/usr/bin/env python3 """ ESP-IDF自动安装脚本 (Python版本) """ import argparse import subprocess import os import sys import platform import shutil import re # 默认设置 DEFAULT_VERSION = "latest" ESP_IDF_REPO = "https://github.com/espressif/esp-idf.git" DEFAULT_VERSION_COUNT = 10 def detect_os(): """检测操作系统类型""" system = platform.system().lower() if system == "linux": # 检测具体的Linux发行版 if os.path.exists("/etc/debian_version"): return "debian" elif os.path.exists("/etc/centos-release"): return "centos" elif os.path.exists("/etc/arch-release"): return "arch" else: return "unknown" elif system == "darwin": return "macos" else: return "unknown" def install_dependencies(os_type): """安装依赖包""" try: if os_type == "debian": print("正在安装Debian/Ubuntu依赖包...") subprocess.run(["sudo", "apt", "update"], check=True) subprocess.run([ "sudo", "apt", "install", "-y", "git", "wget", "flex", "bison", "gperf", "python3", "python3-pip", "python3-venv", "cmake", "ninja-build", "ccache", "libffi-dev", "libssl-dev", "dfu-util", "libusb-1.0-0" ], check=True) elif os_type == "centos": print("正在安装CentOS/RHEL依赖包...") subprocess.run([ "sudo", "yum", "install", "-y", "git", "wget", "flex", "bison", "gperf", "python3", "python3-setuptools", "cmake", "ninja-build", "ccache", "dfu-util", "libusbx" ], check=True) elif os_type == "arch": print("正在安装Arch Linux依赖包...") subprocess.run([ "sudo", "pacman", "-Syu", "--noconfirm", "gcc", "git", "make", "flex", "bison", "gperf", "python", "cmake", "ninja", "ccache", "dfu-util", "libusb", "python-pip" ], check=True) elif os_type == "macos": print("正在安装macOS依赖包...") # 检查是否安装了Homebrew if not shutil.which("brew"): print("请先安装Homebrew: https://brew.sh/") sys.exit(1) subprocess.run([ "brew", "install", "cmake", "ninja", "dfu-util", "ccache" ], check=True) else: print(f"不支持的操作系统类型: {os_type}") sys.exit(1) except subprocess.CalledProcessError as e: print(f"安装依赖包时出错: {e}") sys.exit(1) def install_qemu_dependencies(os_type): """安装QEMU的依赖包""" try: if os_type == "debian": print("正在安装QEMU的Debian/Ubuntu依赖包...") subprocess.run([ "sudo", "apt", "install", "-y", "libgcrypt20", "libglib2.0-0", "libpixman-1-0", "libsdl2-2.0-0", "libslirp0" ], check=True) elif os_type == "centos": print("正在安装QEMU的CentOS/RHEL依赖包...") subprocess.run([ "sudo", "yum", "install", "-y", "--enablerepo=powertools", "libgcrypt", "glib2", "pixman", "SDL2", "libslirp" ], check=True) elif os_type == "arch": print("正在安装QEMU的Arch Linux依赖包...") subprocess.run([ "sudo", "pacman", "-S", "--needed", "--noconfirm", "libgcrypt", "glib2", "pixman", "sdl2", "libslirp" ], check=True) elif os_type == "macos": print("正在安装QEMU的macOS依赖包...") # 检查是否安装了Homebrew if not shutil.which("brew"): print("请先安装Homebrew: https://brew.sh/") sys.exit(1) subprocess.run([ "brew", "install", "libgcrypt", "glib", "pixman", "sdl2", "libslirp" ], check=True) else: print(f"不支持的操作系统类型: {os_type}") sys.exit(1) except subprocess.CalledProcessError as e: print(f"安装QEMU依赖包时出错: {e}") sys.exit(1) def get_remote_versions(count=DEFAULT_VERSION_COUNT): """获取远端版本列表""" print("正在获取ESP-IDF版本列表...") try: # 使用git ls-remote获取tags,并提取版本号 result = subprocess.run( ["git", "ls-remote", "--tags", ESP_IDF_REPO], capture_output=True, text=True, check=True ) # 过滤版本号 versions = [] for line in result.stdout.split('\n'): if line: tag = line.split('/')[-1] # 过滤掉带有^{}的行,这些是轻量级标签的解引用 if re.match(r'^v[0-9]+(\.[0-9]+)*$', tag) and '{}' not in tag: versions.append(tag) # 按版本号排序(降序) versions.sort(key=lambda x: [int(num) for num in x[1:].split('.')], reverse=True) # 返回指定数量的版本 return versions[:count] except subprocess.CalledProcessError as e: print(f"获取版本列表时出错: {e}") return [] def install_esp_idf(version, install_qemu=False): """安装ESP-IDF""" install_path = os.path.join(os.path.expanduser("~"), "esp", version) # 创建安装目录 os.makedirs(install_path, exist_ok=True) # 克隆指定版本的ESP-IDF print(f"正在克隆ESP-IDF {version}...") try: subprocess.run([ "git", "clone", "-b", version, "--recursive", ESP_IDF_REPO, os.path.join(install_path, "esp-idf") ], check=True) # 设置环境变量 os.environ["IDF_GITHUB_ASSETS"] = "dl.espressif.com/github_assets" os.environ["IDF_TOOLS_PATH"] = os.path.join(install_path, "espressif") # 进入ESP-IDF目录并执行安装脚本 esp_idf_path = os.path.join(install_path, "esp-idf") os.chdir(esp_idf_path) subprocess.run(["./install.sh"], check=True) print(f"ESP-IDF {version} 已成功安装到 {esp_idf_path}") # 如果需要安装QEMU if install_qemu: print("正在安装QEMU...") # 安装QEMU依赖 os_type = detect_os() install_qemu_dependencies(os_type) # 使用idf_tools.py安装QEMU subprocess.run([ "python", os.path.join(esp_idf_path, "tools", "idf_tools.py"), "install", "qemu-xtensa", "qemu-riscv32" ], check=True) print("QEMU已成功安装") except subprocess.CalledProcessError as e: print(f"安装ESP-IDF或QEMU时出错: {e}") sys.exit(1) def interactive_mode(): """交互式界面""" print("欢迎使用ESP-IDF自动安装脚本!") # 检测操作系统 os_type = detect_os() print(f"检测到的操作系统: {os_type}") # 询问是否安装依赖 print() reply = input("是否需要安装系统依赖包?[y/N]: ").strip().lower() if reply in ['y', 'yes']: print("开始安装系统依赖包...") install_dependencies(os_type) print("系统依赖包安装完成。") else: print("跳过系统依赖包安装。") # 询问是否安装QEMU print() install_qemu = False reply = input("是否需要安装QEMU模拟器?[y/N]: ").strip().lower() if reply in ['y', 'yes']: install_qemu = True print("将在安装ESP-IDF后安装QEMU模拟器。") else: print("跳过QEMU模拟器安装。") # 获取远端版本列表 page = 1 per_page = 10 selected_version = None while selected_version is None: print() print("正在获取ESP-IDF版本列表...") # 获取所有版本 total_versions = get_remote_versions(1000) # 获取足够多的版本 total_pages = (len(total_versions) + per_page - 1) // per_page if not total_versions: print("无法获取版本列表") sys.exit(1) # 显示当前页的版本(带编号) start_index = (page - 1) * per_page end_index = min(page * per_page, len(total_versions)) versions = total_versions[start_index:end_index] print(f"可用的ESP-IDF版本 (第 {page} 页,共 {total_pages} 页):") for i, version in enumerate(versions, 1): print(f"{i:2d}. {version}") # 如果总页数大于1,显示翻页提示 if total_pages > 1: print() print("导航: [P]上一页 [N]下一页 [数字]指定页码") print(f"选择: 输入版本编号(1-{len(versions)}) 或使用导航命令") choice = input("请选择操作: ").strip() if choice.lower() == 'p': if page > 1: page -= 1 else: print("已经是第一页") input("按回车键继续...") continue elif choice.lower() == 'n': if page < total_pages: page += 1 else: print("已经是最后一页") input("按回车键继续...") continue elif choice.isdigit(): choice_num = int(choice) if 1 <= choice_num <= len(versions): selected_version = versions[choice_num - 1] elif 1 <= choice_num <= total_pages: page = choice_num continue else: print("输入超出范围") input("按回车键继续...") continue else: print("无效选择") input("按回车键继续...") continue else: # 只有一页时直接让用户选择版本 print() print(f"选择: 输入版本编号(1-{len(versions)})") choice = input("请选择要安装的版本(默认为最新版本): ").strip() if not choice: # 选择最新的稳定版本(第一个) selected_version = versions[0] if versions else None break elif choice.isdigit() and 1 <= int(choice) <= len(versions): selected_version = versions[int(choice) - 1] break else: print("无效选择,将使用默认版本。") selected_version = versions[0] if versions else None # 不需要输入回车键继续,直接跳出循环 break print() print(f"将要安装的版本: {selected_version}") # 确认安装 print() reply = input("确认安装?[Y/n]: ").strip().lower() if reply in ['n', 'no']: print("安装已取消。") sys.exit(0) # 安装ESP-IDF和QEMU(如果需要) install_esp_idf(selected_version, install_qemu) def main(): """主程序逻辑""" parser = argparse.ArgumentParser(description="ESP-IDF自动安装脚本") parser.add_argument("--version", help="指定要安装的ESP-IDF版本(git tag)") parser.add_argument("--list-versions", action="store_true", help="列出可用的ESP-IDF版本") parser.add_argument("--version-count", type=int, default=DEFAULT_VERSION_COUNT, help="指定列出的版本数量(默认:10)") parser.add_argument("--install-qemu", action="store_true", help="在安装ESP-IDF后安装QEMU模拟器") args = parser.parse_args() # 如果只需要列出版本列表 if args.list_versions: versions = get_remote_versions(args.version_count) for version in versions: print(version) sys.exit(0) # 如果指定了版本参数,直接安装 if args.version: install_esp_idf(args.version, args.install_qemu) else: # 否则进入交互式模式 interactive_mode() if __name__ == "__main__": main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jasper-zsh/espidf-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server