Skip to content

Commit 98c0e05

Browse files
committed
Fix gitignore to allow llvm source directory to be tracked
1 parent 95a21a6 commit 98c0e05

File tree

3 files changed

+631
-1
lines changed

3 files changed

+631
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tmp/
44
**/.*/settings.local.json
55

66
# LLVM (extracted from archive for Windows development)
7-
llvm/
7+
/llvm/
88

99
# Cargo config with machine-specific LLVM paths
1010
.cargo/config.toml
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//! LLVM configuration management for `.cargo/config.toml`
2+
3+
#![allow(clippy::missing_errors_doc)]
4+
5+
use crate::errors::{Error, Result};
6+
use crate::llvm::{
7+
find_cargo_project_root, find_llvm_14, get_repo_root_from_manifest, is_valid_llvm_14,
8+
};
9+
use std::fs;
10+
use std::path::{Path, PathBuf};
11+
12+
/// Automatically configure LLVM for PECOS
13+
///
14+
/// This function determines the best LLVM 14 installation to use and writes
15+
/// it to `.cargo/config.toml` with `force=true`.
16+
///
17+
/// Priority order:
18+
/// 1. `~/.pecos/llvm` (PECOS-managed LLVM)
19+
/// 2. `LLVM_SYS_140_PREFIX` environment variable
20+
/// 3. System LLVM 14 (Homebrew, system paths, etc.)
21+
///
22+
/// # Errors
23+
///
24+
/// Returns an error if no suitable LLVM 14 installation could be found
25+
pub fn auto_configure_llvm(project_root: Option<PathBuf>) -> Result<PathBuf> {
26+
// Priority 1: Check ~/.pecos/ for PECOS-managed LLVM
27+
if let Some(home_dir) = dirs::home_dir() {
28+
let pecos_dir = home_dir.join(".pecos");
29+
30+
#[cfg(target_os = "windows")]
31+
let pecos_llvm_paths = vec![pecos_dir.join("LLVM-14"), pecos_dir.join("llvm")];
32+
33+
#[cfg(not(target_os = "windows"))]
34+
let pecos_llvm_paths = vec![pecos_dir.join("llvm")];
35+
36+
for pecos_llvm in pecos_llvm_paths {
37+
if is_valid_llvm_14(&pecos_llvm) {
38+
let project_root = project_root
39+
.or_else(get_repo_root_from_manifest)
40+
.or_else(find_cargo_project_root)
41+
.ok_or_else(|| Error::Config("Could not find Cargo project root".into()))?;
42+
43+
write_cargo_config(&project_root, &pecos_llvm, true)?;
44+
return Ok(pecos_llvm);
45+
}
46+
}
47+
}
48+
49+
// Priority 2: Check LLVM_SYS_140_PREFIX
50+
if let Ok(sys_prefix) = std::env::var("LLVM_SYS_140_PREFIX") {
51+
let path = PathBuf::from(&sys_prefix);
52+
if is_valid_llvm_14(&path) {
53+
let project_root = project_root
54+
.or_else(get_repo_root_from_manifest)
55+
.or_else(find_cargo_project_root)
56+
.ok_or_else(|| Error::Config("Could not find Cargo project root".into()))?;
57+
58+
write_cargo_config(&project_root, &path, true)?;
59+
return Ok(path);
60+
}
61+
}
62+
63+
// Priority 3: Scan system for LLVM 14
64+
let repo_root = get_repo_root_from_manifest();
65+
if let Some(detected_path) = find_llvm_14(repo_root) {
66+
let project_root = project_root
67+
.or_else(get_repo_root_from_manifest)
68+
.or_else(find_cargo_project_root)
69+
.ok_or_else(|| Error::Config("Could not find Cargo project root".into()))?;
70+
71+
write_cargo_config(&project_root, &detected_path, true)?;
72+
return Ok(detected_path);
73+
}
74+
75+
Err(Error::Llvm("No suitable LLVM 14 installation found".into()))
76+
}
77+
78+
/// Write or update `.cargo/config.toml` with LLVM configuration
79+
///
80+
/// # Arguments
81+
/// * `project_root` - Path to the Cargo project root
82+
/// * `llvm_path` - Path to the LLVM installation
83+
/// * `force` - If true, use `force=true` to override shell environment variables
84+
pub fn write_cargo_config(project_root: &Path, llvm_path: &Path, force: bool) -> Result<()> {
85+
let cargo_dir = project_root.join(".cargo");
86+
let config_path = cargo_dir.join("config.toml");
87+
88+
fs::create_dir_all(&cargo_dir)?;
89+
90+
// Convert path to forward slashes for TOML compatibility
91+
let llvm_path_str = llvm_path.to_string_lossy().replace('\\', "/");
92+
93+
let llvm_line = if force {
94+
format!("LLVM_SYS_140_PREFIX = {{ value = \"{llvm_path_str}\", force = true }}")
95+
} else {
96+
format!("LLVM_SYS_140_PREFIX = \"{llvm_path_str}\"")
97+
};
98+
99+
let existing_content = fs::read_to_string(&config_path).unwrap_or_default();
100+
101+
// Check if config already has correct LLVM_SYS_140_PREFIX
102+
if existing_content.contains("LLVM_SYS_140_PREFIX") {
103+
let simple_format = format!("LLVM_SYS_140_PREFIX = \"{llvm_path_str}\"");
104+
let force_format =
105+
format!("LLVM_SYS_140_PREFIX = {{ value = \"{llvm_path_str}\", force = true }}");
106+
107+
if (force && existing_content.contains(&force_format))
108+
|| (!force && existing_content.contains(&simple_format))
109+
{
110+
return Ok(());
111+
}
112+
113+
// Update existing configuration
114+
let lines: Vec<&str> = existing_content.lines().collect();
115+
let mut new_lines = Vec::new();
116+
let mut in_env_section = false;
117+
let mut updated = false;
118+
let mut skip_next_lines = 0;
119+
120+
for (i, line) in lines.iter().enumerate() {
121+
if skip_next_lines > 0 {
122+
skip_next_lines -= 1;
123+
continue;
124+
}
125+
126+
let trimmed = line.trim();
127+
128+
if trimmed.starts_with('[') {
129+
in_env_section = trimmed == "[env]";
130+
}
131+
132+
if in_env_section && trimmed.starts_with("LLVM_SYS_140_PREFIX") {
133+
new_lines.push(llvm_line.clone());
134+
updated = true;
135+
136+
if trimmed.contains('{') && !trimmed.contains('}') {
137+
for line in lines.iter().skip(i + 1) {
138+
skip_next_lines += 1;
139+
if line.contains('}') {
140+
break;
141+
}
142+
}
143+
}
144+
} else {
145+
new_lines.push((*line).to_string());
146+
}
147+
}
148+
149+
if updated {
150+
fs::write(&config_path, new_lines.join("\n"))?;
151+
return Ok(());
152+
}
153+
}
154+
155+
// No LLVM configuration exists, append it
156+
let llvm_config = format!(
157+
"\n# LLVM configuration for PECOS\n\
158+
[env]\n\
159+
{llvm_line}\n"
160+
);
161+
162+
let new_content = if existing_content.is_empty() {
163+
llvm_config.trim_start().to_string()
164+
} else {
165+
format!("{existing_content}{llvm_config}")
166+
};
167+
168+
fs::write(&config_path, new_content)?;
169+
Ok(())
170+
}

0 commit comments

Comments
 (0)