v0.1.3-rc.1

This commit is contained in:
wisdgod
2024-12-30 23:29:37 +08:00
parent ea1acb555f
commit 5505ccc6cb
41 changed files with 9626 additions and 1215 deletions

View File

@@ -1,158 +1,126 @@
# <EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Blue }
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
function Write-Error { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 }
# 参数处理
param(
[switch]$Static,
[switch]$Help,
[ValidateSet("x86_64", "aarch64", "i686")]
[string]$Architecture
)
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>
function Test-Requirements {
$tools = @("cargo", "protoc", "npm", "node")
$missing = @()
# 设置错误时停止执行
$ErrorActionPreference = "Stop"
foreach ($tool in $tools) {
if (!(Get-Command $tool -ErrorAction SilentlyContinue)) {
$missing += $tool
}
}
# 颜色输出函数
function Write-Info { param($Message) Write-Host "[INFO] $Message" -ForegroundColor Blue }
function Write-Warn { param($Message) Write-Host "[WARN] $Message" -ForegroundColor Yellow }
function Write-Error { param($Message) Write-Host "[ERROR] $Message" -ForegroundColor Red; exit 1 }
if ($missing.Count -gt 0) {
Write-Error "ȱ<EFBFBD>ٱ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $($missing -join ', ')"
}
}
# 检查必要的工具
function Check-Requirements {
$tools = @("cargo", "protoc", "npm", "node")
$missing = @()
# <20><> Test-Requirements <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>º<EFBFBD><C2BA><EFBFBD>
function Initialize-VSEnvironment {
Write-Info "<EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD> Visual Studio <20><><EFBFBD><EFBFBD>..."
# ֱ<><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>֪<EFBFBD><D6AA> vcvarsall.bat ·<><C2B7>
$vcvarsallPath = "E:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"
if (-not (Test-Path $vcvarsallPath)) {
Write-Error "δ<EFBFBD>ҵ<EFBFBD> vcvarsall.bat: $vcvarsallPath"
return
}
Write-Info "ʹ<EFBFBD><EFBFBD> vcvarsall.bat ·<><C2B7>: $vcvarsallPath"
# <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$archArg = "x64"
$command = "`"$vcvarsallPath`" $archArg && set"
try {
$output = cmd /c "$command" 2>&1
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>ִ<EFBFBD><D6B4>
if ($LASTEXITCODE -ne 0) {
Write-Error "vcvarsall.bat ִ<><D6B4>ʧ<EFBFBD>ܣ<EFBFBD><DCA3>˳<EFBFBD><CBB3><EFBFBD>: $LASTEXITCODE"
return
foreach ($tool in $tools) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) {
$missing += $tool
}
# <20><><EFBFBD>µ<EFBFBD>ǰ PowerShell <20><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
foreach ($line in $output) {
if ($line -match "^([^=]+)=(.*)$") {
$name = $matches[1]
$value = $matches[2]
if (![string]::IsNullOrEmpty($name)) {
Set-Item -Path "env:$name" -Value $value -ErrorAction SilentlyContinue
}
}
}
Write-Info "Visual Studio <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
}
catch {
Write-Error "<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD> Visual Studio <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $_"
if ($missing.Count -gt 0) {
Write-Error "缺少必要工具: $($missing -join ', ')"
}
}
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
# 帮助信息
function Show-Help {
Write-Host @"
<EFBFBD>÷<EFBFBD>: $(Split-Path $MyInvocation.MyCommand.Path -Leaf) [ѡ<EFBFBD><EFBFBD>]
Write-Host @"
: $(Split-Path $MyInvocation.ScriptName -Leaf) []
ѡ<EFBFBD><EFBFBD>:
--static ʹ<EFBFBD>þ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>Ĭ<EFBFBD>϶<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>
--help <EFBFBD><EFBFBD>ʾ<EFBFBD>˰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
:
-Static 使
-Help
Ĭ<EFBFBD>ϱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Windows ֧<EFBFBD>ֵļܹ<EFBFBD> (x64 <EFBFBD><EFBFBD> arm64)
使
"@
}
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
function New-Target {
param (
[string]$target,
[string]$rustflags
)
# 构建函数
function Build-Target {
param (
[string]$Target,
[string]$RustFlags
)
Write-Info "<EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD> $target..."
Write-Info "正在构建 $Target..."
# <EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>
$env:RUSTFLAGS = $rustflags
cargo build --target $target --release
# 设置环境变量
$env:RUSTFLAGS = $RustFlags
# <EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$binaryName = "cursor-api"
if ($UseStatic) {
$binaryName += "-static"
}
# 构建
if ($Target -ne (rustc -Vv | Select-String "host: (.*)" | ForEach-Object { $_.Matches.Groups[1].Value })) {
cargo build --target $Target --release
} else {
cargo build --release
}
$sourcePath = "target/$target/release/cursor-api.exe"
$targetPath = "release/${binaryName}-${target}.exe"
# 移动编译产物到 release 目录
$binaryName = "cursor-api"
if ($Static) {
$binaryName += "-static"
}
if (Test-Path $sourcePath) {
Copy-Item $sourcePath $targetPath -Force
Write-Info "<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD> $target"
}
else {
Write-Warn "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>ҵ<EFBFBD>: $target"
return $false
}
return $true
$binaryPath = if ($Target -eq (rustc -Vv | Select-String "host: (.*)" | ForEach-Object { $_.Matches.Groups[1].Value })) {
"target/release/cursor-api.exe"
} else {
"target/$Target/release/cursor-api.exe"
}
if (Test-Path $binaryPath) {
Copy-Item $binaryPath "release/$binaryName-$Target.exe"
Write-Info "完成构建 $Target"
} else {
Write-Warn "构建产物未找到: $Target"
Write-Warn "查找路径: $binaryPath"
Write-Warn "当前目录内容:"
Get-ChildItem -Recurse target/
return $false
}
return $true
}
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$UseStatic = $false
foreach ($arg in $args) {
switch ($arg) {
"--static" { $UseStatic = $true }
"--help" { Show-Help; exit 0 }
default { Write-Error "δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $arg" }
}
if ($Help) {
Show-Help
exit 0
}
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
try {
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Test-Requirements
# 检查依赖
Check-Requirements
# <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD> Visual Studio <20><><EFBFBD><EFBFBD>
Initialize-VSEnvironment
# 创建 release 目录
New-Item -ItemType Directory -Force -Path release | Out-Null
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD> release Ŀ¼
New-Item -ItemType Directory -Force -Path "release" | Out-Null
# <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>ƽ̨
$targets = @(
"x86_64-pc-windows-msvc",
"aarch64-pc-windows-msvc"
)
# <20><><EFBFBD>þ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD>ӱ<EFBFBD>־
$rustflags = ""
if ($UseStatic) {
$rustflags = "-C target-feature=+crt-static"
}
Write-Info "<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>..."
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>
foreach ($target in $targets) {
New-Target -target $target -rustflags $rustflags
}
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>"
# 设置静态链接标志
$rustFlags = ""
if ($Static) {
$rustFlags = "-C target-feature=+crt-static"
}
catch {
Write-Error "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $_"
}
# 获取目标架构
$arch = if ($Architecture) {
$Architecture
} else {
switch ($env:PROCESSOR_ARCHITECTURE) {
"AMD64" { "x86_64" }
"ARM64" { "aarch64" }
"X86" { "i686" }
default { Write-Error "不支持的架构: $env:PROCESSOR_ARCHITECTURE" }
}
}
$target = "$arch-pc-windows-msvc"
Write-Info "开始构建..."
if (-not (Build-Target -Target $target -RustFlags $rustFlags)) {
Write-Error "构建失败"
}
Write-Info "构建完成!"

View File

@@ -6,11 +6,6 @@ info() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
error() { echo -e "\033[1;31m[ERROR]\033[0m $*" >&2; exit 1; }
# 检查是否在 Linux 环境
is_linux() {
[ "$(uname -s)" = "Linux" ]
}
# 检查必要的工具
check_requirements() {
local missing_tools=()
@@ -22,23 +17,29 @@ check_requirements() {
fi
done
# cross 工具检查(仅在 Linux 上需要)
if [[ "$OS" == "Linux" ]] && ! command -v cross &>/dev/null; then
missing_tools+=("cross")
fi
if [[ ${#missing_tools[@]} -gt 0 ]]; then
error "缺少必要工具: ${missing_tools[*]}"
fi
}
# 解析参数
USE_STATIC=false
while [[ $# -gt 0 ]]; do
case $1 in
--static) USE_STATIC=true ;;
--help) show_help; exit 0 ;;
*) error "未知参数: $1" ;;
esac
shift
done
# 帮助信息
show_help() {
cat << EOF
用法: $(basename "$0") [选项]
选项:
--cross 使用 cross 进行交叉编译(仅在 Linux 上有效)
--static 使用静态链接(默认动态链接)
--help 显示此帮助信息
@@ -46,22 +47,6 @@ show_help() {
EOF
}
# 判断是否使用 cross
should_use_cross() {
local target=$1
# 如果不是 Linux 环境,直接返回 false
if [[ "$OS" != "Linux" ]]; then
return 1
fi
# 在 Linux 环境下,以下目标不使用 cross
# 1. Linux 上的 x86_64-unknown-linux-gnu
if [[ "$target" == "x86_64-unknown-linux-gnu" ]]; then
return 1
fi
return 0
}
# 并行构建函数
build_target() {
local target=$1
@@ -73,15 +58,11 @@ build_target() {
# 确定文件后缀
[[ $target == *"windows"* ]] && extension=".exe"
# 判断是否使用 cross
if should_use_cross "$target"; then
env RUSTFLAGS="$rustflags" cross build --target "$target" --release
# 构建
if [[ $target != "$CURRENT_TARGET" ]]; then
env RUSTFLAGS="$rustflags" cargo build --target "$target" --release
else
if [[ $target != "$CURRENT_TARGET" ]]; then
env RUSTFLAGS="$rustflags" cargo build --target "$target" --release
else
env RUSTFLAGS="$rustflags" cargo build --release
fi
env RUSTFLAGS="$rustflags" cargo build --release
fi
# 移动编译产物到 release 目录
@@ -117,7 +98,13 @@ get_target() {
local os=$2
case "$os" in
"Darwin") echo "${arch}-apple-darwin" ;;
"Linux") echo "${arch}-unknown-linux-gnu" ;;
"Linux")
if [[ $USE_STATIC == true ]]; then
echo "${arch}-unknown-linux-musl"
else
echo "${arch}-unknown-linux-gnu"
fi
;;
"MINGW"*|"MSYS"*|"CYGWIN"*|"Windows_NT") echo "${arch}-pc-windows-msvc" ;;
"FreeBSD") echo "${arch}-unknown-freebsd" ;;
*) error "不支持的系统: $os" ;;
@@ -134,16 +121,16 @@ CURRENT_TARGET=$(get_target "$ARCH" "$OS")
get_targets() {
case "$1" in
"linux")
# Linux 构建所有 Linux 目标和 FreeBSD 目标
echo "x86_64-unknown-linux-gnu x86_64-unknown-freebsd"
# Linux 构建当前架构
echo "$CURRENT_TARGET"
;;
"freebsd")
# FreeBSD 只构建当前架构的 FreeBSD 目标
echo "${ARCH}-unknown-freebsd"
# FreeBSD 只构建当前架构
echo "$CURRENT_TARGET"
;;
"windows")
# Windows 构建所有 Windows 目标
echo "x86_64-pc-windows-msvc"
# Windows 构建当前架构
echo "$CURRENT_TARGET"
;;
"macos")
# macOS 构建所有 macOS 目标
@@ -153,33 +140,21 @@ get_targets() {
esac
}
# 解析参数
USE_STATIC=false
while [[ $# -gt 0 ]]; do
case $1 in
--static) USE_STATIC=true ;;
--help) show_help; exit 0 ;;
*) error "未知参数: $1" ;;
esac
shift
done
# 检查依赖
check_requirements
# 确定要构建的目标
case "$OS" in
"Darwin")
Darwin)
TARGETS=($(get_targets "macos"))
;;
"Linux")
Linux)
TARGETS=($(get_targets "linux"))
;;
"FreeBSD")
FreeBSD)
TARGETS=($(get_targets "freebsd"))
;;
"MINGW"*|"MSYS"*|"CYGWIN"*|"Windows_NT")
MINGW*|MSYS*|CYGWIN*|Windows_NT)
TARGETS=($(get_targets "windows"))
;;
*) error "不支持的系统: $OS" ;;
@@ -189,8 +164,8 @@ esac
mkdir -p release
# 设置静态链接标志
RUSTFLAGS=""
[[ $USE_STATIC == true ]] && RUSTFLAGS="-C target-feature=+crt-static"
RUSTFLAGS="-C link-arg=-s"
[[ $USE_STATIC == true ]] && RUSTFLAGS="-C target-feature=+crt-static -C link-arg=-s"
# 并行构建所有目标
info "开始构建..."

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env node
const { minify } = require('html-minifier-terser');
const fs = require('fs');
const path = require('path');
// 配置选项
const options = {
collapseWhitespace: true,
removeComments: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyCSS: true,
minifyJS: true,
processScripts: ['application/json'],
};
// 处理文件
async function minifyFile(inputPath, outputPath) {
try {
const html = fs.readFileSync(inputPath, 'utf8');
const minified = await minify(html, options);
fs.writeFileSync(outputPath, minified);
console.log(`✓ Minified ${path.basename(inputPath)} -> ${path.basename(outputPath)}`);
} catch (err) {
console.error(`✗ Error processing ${inputPath}:`, err);
process.exit(1);
}
}
// 主函数
async function main() {
const staticDir = path.join(__dirname, '..', 'static');
const files = [
['tokeninfo.html', 'tokeninfo.min.html'],
];
for (const [input, output] of files) {
await minifyFile(
path.join(staticDir, input),
path.join(staticDir, output)
);
}
}
main();

81
scripts/minify.js Normal file
View File

@@ -0,0 +1,81 @@
#!/usr/bin/env node
const { minify: minifyHtml } = require('html-minifier-terser');
const { minify: minifyJs } = require('terser');
const CleanCSS = require('clean-css');
const fs = require('fs');
const path = require('path');
// 配置选项
const options = {
collapseWhitespace: true,
removeComments: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyCSS: true,
minifyJS: true,
processScripts: ['application/json'],
};
// CSS 压缩选项
const cssOptions = {
level: 2
};
// 处理文件
async function minifyFile(inputPath, outputPath) {
try {
const ext = path.extname(inputPath).toLowerCase();
const content = fs.readFileSync(inputPath, 'utf8');
let minified;
switch (ext) {
case '.html':
minified = await minifyHtml(content, options);
break;
case '.js':
const result = await minifyJs(content);
minified = result.code;
break;
case '.css':
minified = new CleanCSS(cssOptions).minify(content).styles;
break;
default:
throw new Error(`Unsupported file type: ${ext}`);
}
fs.writeFileSync(outputPath, minified);
console.log(`✓ Minified ${path.basename(inputPath)} -> ${path.basename(outputPath)}`);
} catch (err) {
console.error(`✗ Error processing ${inputPath}:`, err);
process.exit(1);
}
}
// 主函数
async function main() {
// 获取命令行参数跳过前两个参数node和脚本路径
const files = process.argv.slice(2);
if (files.length === 0) {
console.error('No input files specified');
process.exit(1);
}
const staticDir = path.join(__dirname, '..', 'static');
for (const file of files) {
const inputPath = path.join(staticDir, file);
const ext = path.extname(file);
const outputPath = path.join(
staticDir,
file.replace(ext, `.min${ext}`)
);
await minifyFile(inputPath, outputPath);
}
}
main();

View File

@@ -8,7 +8,9 @@
"name": "html-minifier-scripts",
"version": "1.0.0",
"dependencies": {
"html-minifier-terser": "^7.2.0"
"clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0",
"terser": "^5.37.0"
},
"engines": {
"node": ">=14.0.0"

View File

@@ -6,6 +6,8 @@
"node": ">=14.0.0"
},
"dependencies": {
"html-minifier-terser": "^7.2.0"
"clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0",
"terser": "^5.37.0"
}
}
}

View File

@@ -1,31 +0,0 @@
# <20><><EFBFBD><EFBFBD> PowerShell <20><><EFBFBD><EFBFBD>Ϊ UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Թ<EFBFBD><D4B9><EFBFBD>ԱȨ<D4B1><C8A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Warning "<EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD>ԱȨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д˽ű<EFBFBD>"
exit 1
}
# <20><><EFBFBD><EFBFBD><E9B2A2>װ Chocolatey
if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
Write-Output "<EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD>װ Chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
}
# <20><>װ<EFBFBD><D7B0>Ҫ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD>
Write-Output "<EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD>װ<EFBFBD><EFBFBD>Ҫ<EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>..."
choco install -y mingw
choco install -y protoc
choco install -y git
# <20><>װ Rust <20><><EFBFBD><EFBFBD>
Write-Output "<EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD>װ Rust <20><><EFBFBD><EFBFBD>..."
rustup target add x86_64-pc-windows-msvc
rustup target add x86_64-unknown-linux-gnu
cargo install cross
Write-Output "<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>"

179
scripts/setup.ps1 Normal file
View File

@@ -0,0 +1,179 @@
# <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>ʱִֹͣ<D6B9><D6B4>
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue" # <20>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
# <20><>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
function Write-Info { param($Message) Write-Host "[INFO] $Message" -ForegroundColor Blue }
function Write-Warn { param($Message) Write-Host "[WARN] $Message" -ForegroundColor Yellow }
function Write-Success { param($Message) Write-Host "[SUCCESS] $Message" -ForegroundColor Green }
function Write-Error { param($Message) Write-Host "[ERROR] $Message" -ForegroundColor Red; exit 1 }
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԱȨ<D4B1><C8A8>
function Test-Administrator {
$user = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal $user
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
if (-not (Test-Administrator)) {
Write-Error "<EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD>ԱȨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д˽ű<EFBFBD>"
}
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
function Show-Help {
Write-Host @"
<EFBFBD>÷<EFBFBD>: $(Split-Path $MyInvocation.ScriptName -Leaf) [ѡ<EFBFBD><EFBFBD>]
ѡ<EFBFBD><EFBFBD>:
-NoVS <EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ Visual Studio Build Tools
-NoRust <EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ Rust
-NoNode <EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ Node.js
-Help <EFBFBD><EFBFBD>ʾ<EFBFBD>˰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
ʾ<EFBFBD><EFBFBD>:
.\setup.ps1
.\setup.ps1 -NoVS
.\setup.ps1 -NoRust -NoNode
"@
}
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
param(
[switch]$NoVS,
[switch]$NoRust,
[switch]$NoNode,
[switch]$Help
)
if ($Help) {
Show-Help
exit 0
}
# <20><><EFBFBD><EFBFBD><E9B2A2>װ Chocolatey
function Install-Chocolatey {
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Chocolatey..."
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
Write-Info "<EFBFBD><EFBFBD>װ Chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
try {
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
}
catch {
Write-Error "<EFBFBD><EFBFBD>װ Chocolatey ʧ<><CAA7>: $_"
}
# ˢ<>»<EFBFBD><C2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
}
# <20><>װ Visual Studio Build Tools
function Install-VSBuildTools {
if ($NoVS) {
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Visual Studio Build Tools <20><>װ"
return
}
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Visual Studio Build Tools..."
$vsPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (-not (Test-Path $vsPath)) {
Write-Info "<EFBFBD><EFBFBD>װ Visual Studio Build Tools..."
try {
# <20><><EFBFBD>ذ<EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>
$vsInstallerUrl = "https://aka.ms/vs/17/release/vs_BuildTools.exe"
$vsInstallerPath = "$env:TEMP\vs_BuildTools.exe"
Invoke-WebRequest -Uri $vsInstallerUrl -OutFile $vsInstallerPath
# <20><>װ
$process = Start-Process -FilePath $vsInstallerPath -ArgumentList `
"--quiet", "--wait", "--norestart", "--nocache", `
"--installPath", "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools", `
"--add", "Microsoft.VisualStudio.Workload.VCTools" `
-NoNewWindow -Wait -PassThru
if ($process.ExitCode -ne 0) {
Write-Error "Visual Studio Build Tools <20><>װʧ<D7B0><CAA7>"
}
Remove-Item $vsInstallerPath -Force
}
catch {
Write-Error "<EFBFBD><EFBFBD>װ Visual Studio Build Tools ʧ<><CAA7>: $_"
}
}
else {
Write-Info "Visual Studio Build Tools <20>Ѱ<EFBFBD>װ"
}
}
# <20><>װ Rust
function Install-Rust {
if ($NoRust) {
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Rust <20><>װ"
return
}
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Rust..."
if (-not (Get-Command rustc -ErrorAction SilentlyContinue)) {
Write-Info "<EFBFBD><EFBFBD>װ Rust..."
try {
$rustupInit = "$env:TEMP\rustup-init.exe"
Invoke-WebRequest -Uri "https://win.rustup.rs" -OutFile $rustupInit
Start-Process -FilePath $rustupInit -ArgumentList "-y" -Wait
Remove-Item $rustupInit -Force
# ˢ<>»<EFBFBD><C2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
catch {
Write-Error "<EFBFBD><EFBFBD>װ Rust ʧ<><CAA7>: $_"
}
}
# <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>ƽ̨
Write-Info "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Rust Ŀ<><C4BF>ƽ̨..."
$arch = if ([Environment]::Is64BitOperatingSystem) { "x86_64" } else { "i686" }
rustup target add "$arch-pc-windows-msvc"
}
# <20><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
function Install-Tools {
Write-Info "<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>..."
# <20><>װ protoc
if (-not (Get-Command protoc -ErrorAction SilentlyContinue)) {
Write-Info "<EFBFBD><EFBFBD>װ Protocol Buffers..."
choco install -y protoc
}
# <20><>װ Git
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Info "<EFBFBD><EFBFBD>װ Git..."
choco install -y git
}
# <20><>װ Node.js
if (-not $NoNode -and -not (Get-Command node -ErrorAction SilentlyContinue)) {
Write-Info "<EFBFBD><EFBFBD>װ Node.js..."
choco install -y nodejs
}
# ˢ<>»<EFBFBD><C2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
try {
Write-Info "<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>..."
Install-Chocolatey
Install-VSBuildTools
Install-Rust
Install-Tools
Write-Success "<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>"
}
catch {
Write-Error "<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD>: $_"
}

157
scripts/setup.sh Normal file
View File

@@ -0,0 +1,157 @@
#!/bin/bash
# 设置错误时退出
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
info() {
echo -e "${BLUE}[INFO] $1${NC}"
}
error() {
echo -e "${RED}[ERROR] $1${NC}"
exit 1
}
# 检查是否为 root 用户FreeBSD 和 Linux
if [ "$(uname)" != "Darwin" ] && [ "$EUID" -ne 0 ]; then
error "请使用 root 权限运行此脚本 (sudo ./setup.sh)"
fi
# 检测包管理器
if command -v brew &> /dev/null; then
PKG_MANAGER="brew"
info "检测到 macOS/Homebrew 系统"
elif command -v pkg &> /dev/null; then
PKG_MANAGER="pkg"
info "检测到 FreeBSD 系统"
elif command -v apt-get &> /dev/null; then
PKG_MANAGER="apt-get"
info "检测到 Debian/Ubuntu 系统"
elif command -v dnf &> /dev/null; then
PKG_MANAGER="dnf"
info "检测到 Fedora/RHEL 系统"
elif command -v yum &> /dev/null; then
PKG_MANAGER="yum"
info "检测到 CentOS 系统"
else
error "未检测到支持的包管理器"
fi
# 更新包管理器缓存
info "更新包管理器缓存..."
case $PKG_MANAGER in
"brew")
brew update
;;
"pkg")
pkg update
;;
*)
$PKG_MANAGER update -y
;;
esac
# 安装基础构建工具
info "安装基础构建工具..."
case $PKG_MANAGER in
"brew")
brew install \
protobuf \
pkg-config \
openssl \
curl \
git \
node
;;
"pkg")
pkg install -y \
gmake \
protobuf \
pkgconf \
openssl \
curl \
git \
node
;;
"apt-get")
$PKG_MANAGER install -y --no-install-recommends \
build-essential \
protobuf-compiler \
pkg-config \
libssl-dev \
ca-certificates \
curl \
tzdata \
git
;;
*)
$PKG_MANAGER install -y \
gcc \
gcc-c++ \
make \
protobuf-compiler \
pkg-config \
openssl-devel \
ca-certificates \
curl \
tzdata \
git
;;
esac
# 安装 Node.js 和 npm如果还没有通过包管理器安装
if ! command -v node &> /dev/null && [ "$PKG_MANAGER" != "brew" ] && [ "$PKG_MANAGER" != "pkg" ]; then
info "安装 Node.js 和 npm..."
if [ "$PKG_MANAGER" = "apt-get" ]; then
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
$PKG_MANAGER install -y nodejs
else
curl -fsSL https://rpm.nodesource.com/setup_lts.x | bash -
$PKG_MANAGER install -y nodejs
fi
fi
# 安装 Rust如果未安装
if ! command -v rustc &> /dev/null; then
info "安装 Rust..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
fi
# 添加目标平台
info "添加 Rust 目标平台..."
case "$(uname)" in
"FreeBSD")
rustup target add x86_64-unknown-freebsd
;;
"Darwin")
rustup target add x86_64-apple-darwin aarch64-apple-darwin
;;
*)
rustup target add x86_64-unknown-linux-gnu
;;
esac
# 清理包管理器缓存
case $PKG_MANAGER in
"apt-get")
rm -rf /var/lib/apt/lists/*
;;
"pkg")
pkg clean -y
;;
esac
# 设置时区(除了 macOS
if [ "$(uname)" != "Darwin" ]; then
info "设置时区为 Asia/Shanghai..."
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
fi
echo -e "${GREEN}安装完成!${NC}"