Skip to content

Commit 69dd53d

Browse files
committed
fix: 修复 Rust 运行问题
1 parent 4488a8f commit 69dd53d

3 files changed

Lines changed: 133 additions & 5 deletions

File tree

src-tauri/src/env_providers/rust.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,86 @@ impl RustEnvironmentProvider {
332332
Ok(())
333333
}
334334

335+
fn merge_rust_std(&self, install_path: &Path) -> Result<(), String> {
336+
use std::fs;
337+
338+
info!("合并 Rust 标准库到 rustc 目录");
339+
340+
// 查找所有 rust-std-* 目录
341+
let entries = fs::read_dir(install_path)
342+
.map_err(|e| format!("读取安装目录失败: {}", e))?;
343+
344+
for entry in entries.flatten() {
345+
let path = entry.path();
346+
if path.is_dir() {
347+
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
348+
if name.starts_with("rust-std-") {
349+
info!("找到标准库组件: {}", name);
350+
351+
// 源路径: install_path/rust-std-xxx/lib/rustlib/
352+
let std_rustlib_src = path.join("lib").join("rustlib");
353+
354+
// 目标路径: install_path/rustc/lib/rustlib/
355+
let rustc_rustlib_dst = install_path.join("rustc").join("lib").join("rustlib");
356+
357+
if std_rustlib_src.exists() && rustc_rustlib_dst.exists() {
358+
// 遍历标准库中的所有目标平台
359+
if let Ok(std_entries) = fs::read_dir(&std_rustlib_src) {
360+
for std_entry in std_entries.flatten() {
361+
let std_target_path = std_entry.path();
362+
if std_target_path.is_dir() {
363+
if let Some(target_name) = std_target_path.file_name() {
364+
let dst_target_path = rustc_rustlib_dst.join(target_name);
365+
366+
// 如果目标路径不存在,创建它
367+
if !dst_target_path.exists() {
368+
fs::create_dir_all(&dst_target_path)
369+
.map_err(|e| format!("创建目标目录失败: {}", e))?;
370+
}
371+
372+
// 复制 lib 目录
373+
let std_lib_src = std_target_path.join("lib");
374+
let dst_lib = dst_target_path.join("lib");
375+
376+
if std_lib_src.exists() {
377+
info!("复制标准库: {} -> {}", std_lib_src.display(), dst_lib.display());
378+
Self::copy_dir_all(&std_lib_src, &dst_lib)?;
379+
}
380+
}
381+
}
382+
}
383+
}
384+
}
385+
}
386+
}
387+
}
388+
}
389+
390+
info!("标准库合并完成");
391+
Ok(())
392+
}
393+
394+
fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> {
395+
use std::fs;
396+
397+
fs::create_dir_all(dst).map_err(|e| format!("创建目录失败: {}", e))?;
398+
399+
for entry in fs::read_dir(src).map_err(|e| format!("读取目录失败: {}", e))? {
400+
let entry = entry.map_err(|e| format!("读取条目失败: {}", e))?;
401+
let ty = entry.file_type().map_err(|e| format!("获取文件类型失败: {}", e))?;
402+
let src_path = entry.path();
403+
let dst_path = dst.join(entry.file_name());
404+
405+
if ty.is_dir() {
406+
Self::copy_dir_all(&src_path, &dst_path)?;
407+
} else {
408+
fs::copy(&src_path, &dst_path).map_err(|e| format!("复制文件失败: {}", e))?;
409+
}
410+
}
411+
412+
Ok(())
413+
}
414+
335415
async fn update_plugin_config(
336416
&self,
337417
version: &str,
@@ -350,6 +430,15 @@ impl RustEnvironmentProvider {
350430
let rustc_bin = install_path.join("rustc").join("bin");
351431
let has_rustc_dir = rustc_bin.exists();
352432

433+
// 使用相对路径,工作目录会被设置为 execute_home
434+
#[cfg(target_os = "windows")]
435+
let run_command = if has_rustc_dir {
436+
"rustc\\bin\\rustc $filename -o main.exe && main.exe".to_string()
437+
} else {
438+
"bin\\rustc $filename -o main.exe && main.exe".to_string()
439+
};
440+
441+
#[cfg(not(target_os = "windows"))]
353442
let run_command = if has_rustc_dir {
354443
"rustc/bin/rustc $filename -o /tmp/main && /tmp/main".to_string()
355444
} else {
@@ -523,6 +612,9 @@ impl EnvironmentProvider for RustEnvironmentProvider {
523612
std::fs::remove_dir_all(&temp_extract_dir).ok();
524613
std::fs::remove_file(&temp_file).ok();
525614

615+
// 合并标准库到 rustc 目录
616+
self.merge_rust_std(&install_path)?;
617+
526618
self.update_plugin_config(version, app_handle.clone())
527619
.await?;
528620

@@ -543,6 +635,10 @@ impl EnvironmentProvider for RustEnvironmentProvider {
543635
return Err(format!("版本 {} 未安装", version));
544636
}
545637

638+
// 切换版本时也需要确保标准库已合并
639+
let install_path = self.get_version_install_path(version);
640+
self.merge_rust_std(&install_path)?;
641+
546642
self.update_plugin_config(version, app_handle).await?;
547643
info!("已切换到 Rust {}", version);
548644
Ok(())

src-tauri/src/execution.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,18 @@ pub async fn execute_code(
160160
);
161161

162162
// 启动子进程
163-
let mut child = match Command::new(&cmd)
163+
let mut command = Command::new(&cmd);
164+
command
164165
.args(&args)
165166
.stdout(Stdio::piped())
166-
.stderr(Stdio::piped())
167-
.spawn()
168-
{
167+
.stderr(Stdio::piped());
168+
169+
// 如果插件有 execute_home,设置工作目录
170+
if let Some(execute_home) = plugin.get_execute_home() {
171+
command.current_dir(&execute_home);
172+
}
173+
174+
let mut child = match command.spawn() {
169175
Ok(child) => child,
170176
Err(e) => {
171177
let _execution_time = start_time.elapsed().as_millis();

src-tauri/src/plugins/rust.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,36 @@ impl LanguagePlugin for RustPlugin {
4747
if let Some(config) = self.get_config() {
4848
if let Some(run_cmd) = &config.run_command {
4949
let full_cmd = run_cmd.replace("$filename", file_path);
50+
51+
// Windows 使用 cmd /c,Unix 使用 sh -c
52+
#[cfg(target_os = "windows")]
53+
return vec!["/c".to_string(), full_cmd];
54+
55+
#[cfg(not(target_os = "windows"))]
5056
return vec!["-c".to_string(), full_cmd];
5157
}
5258
}
53-
vec![file_path.to_string()]
59+
60+
// 默认命令
61+
#[cfg(target_os = "windows")]
62+
return vec!["/c".to_string(), format!("rustc {} -o main.exe && main.exe", file_path)];
63+
64+
#[cfg(not(target_os = "windows"))]
65+
vec!["-c".to_string(), format!("rustc {} -o /tmp/main && /tmp/main", file_path)]
66+
}
67+
68+
fn get_command(
69+
&self,
70+
_file_path: Option<&str>,
71+
_is_version: bool,
72+
_file_name: Option<String>,
73+
) -> String {
74+
// Windows 使用 cmd,Unix 使用 sh
75+
#[cfg(target_os = "windows")]
76+
return "cmd".to_string();
77+
78+
#[cfg(not(target_os = "windows"))]
79+
"sh".to_string()
5480
}
5581

5682
fn get_default_config(&self) -> PluginConfig {

0 commit comments

Comments
 (0)