use std::collections::{BTreeMap, BinaryHeap, HashMap, HashSet, VecDeque};
use std::fmt;
use std::fs;
use std::io::{self, BufRead, BufReader, Read, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use crate::clang::clang_real_projects_x86::{
self, X86BuildResult, X86BuildSystem, X86CompileDiagnostic, X86DiagLevel, X86ProjectConfig,
X86RealProjectCompiler, X86TestSuiteResult, DEFAULT_CACHE_DIR, DEFAULT_CACHE_MAX_SIZE,
DEFAULT_PARALLEL_JOBS, X86_32_LINUX_TRIPLE, X86_64_DARWIN_TRIPLE, X86_64_LINUX_TRIPLE,
X86_64_WINDOWS_TRIPLE, X86_CPU_FEATURES, X86_MICROARCHS,
};
use crate::clang::clang_x86_pipeline::{
self, CompilationCache, PipelineResult, X86CompileOptions, X86OptLevel, X86OutputFormat,
X86Pipeline,
};
use crate::clang::{
self, compile_c_file, compile_c_string, CLangStandard, ClangCodeGen, ClangDriver, ClangOptions,
DiagSeverity, DiagnosticBuilder, DiagnosticEngine, DiagnosticOptions,
};
use crate::x86::{
self, X86CallingConvention, X86FrameInfo, X86FrameLowering, X86InstrInfo, X86IsaFeature,
X86RegisterInfo, X86Subtarget, X86TargetMachine, X86_64_REG_COUNT, X86_PAGE_SIZE,
X86_RED_ZONE_SIZE_64, X86_STACK_ALIGNMENT_32, X86_STACK_ALIGNMENT_64,
};
pub fn compare_diagnostics(clang_output: &str, gcc_output: &str) -> DiagnosticComparison {
let clang_errors = count_diagnostic_lines(clang_output, "error:");
let clang_warnings = count_diagnostic_lines(clang_output, "warning:");
let gcc_errors = count_diagnostic_lines(gcc_output, "error:");
let gcc_warnings = count_diagnostic_lines(gcc_output, "warning:");
DiagnosticComparison {
clang_errors,
clang_warnings,
gcc_errors,
gcc_warnings,
clang_unique_warnings: extract_unique_diagnostics(clang_output, gcc_output, "warning:"),
gcc_unique_warnings: extract_unique_diagnostics(gcc_output, clang_output, "warning:"),
}
}
fn count_diagnostic_lines(output: &str, prefix: &str) -> usize {
output.lines().filter(|l| l.contains(prefix)).count()
}
fn extract_unique_diagnostics(a: &str, b: &str, prefix: &str) -> Vec<String> {
let a_diags: HashSet<String> = a
.lines()
.filter(|l| l.contains(prefix))
.map(|l| l.trim().to_string())
.collect();
let b_diags: HashSet<String> = b
.lines()
.filter(|l| l.contains(prefix))
.map(|l| l.trim().to_string())
.collect();
a_diags.difference(&b_diags).cloned().collect()
}
#[derive(Debug, Clone)]
pub struct DiagnosticComparison {
pub clang_errors: usize,
pub clang_warnings: usize,
pub gcc_errors: usize,
pub gcc_warnings: usize,
pub clang_unique_warnings: Vec<String>,
pub gcc_unique_warnings: Vec<String>,
}
impl DiagnosticComparison {
pub fn summary(&self) -> String {
format!(
"Diagnostic Comparison:
\n Clang: {} errors, {} warnings
\n GCC: {} errors, {} warnings
\n Clang-unique warnings: {}
\n GCC-unique warnings: {}",
self.clang_errors,
self.clang_warnings,
self.gcc_errors,
self.gcc_warnings,
self.clang_unique_warnings.len(),
self.gcc_unique_warnings.len(),
)
}
}
#[derive(Debug, Clone)]
pub struct HealthCheckResult {
pub all_passed: bool,
pub checks: Vec<HealthCheckItem>,
pub timestamp: SystemTime,
}
#[derive(Debug, Clone)]
pub struct HealthCheckItem {
pub name: String,
pub passed: bool,
pub message: String,
pub severity: HealthCheckSeverity,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HealthCheckSeverity {
Info,
Warning,
Error,
}
pub fn check_build_environment() -> HealthCheckResult {
let mut checks = Vec::new();
let has_clang = which::which("clang").is_ok();
checks.push(HealthCheckItem {
name: "Clang compiler".to_string(),
passed: has_clang,
message: if has_clang {
let version = Command::new("clang")
.arg("--version")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.and_then(|s| s.lines().next().map(|l| l.to_string()))
.unwrap_or_else(|| "unknown version".to_string());
format!("Clang found: {}", version)
} else {
"Clang not found in PATH".to_string()
},
severity: if has_clang {
HealthCheckSeverity::Info
} else {
HealthCheckSeverity::Error
},
});
let has_lld = which::which("ld.lld")
.or_else(|_| which::which("lld"))
.is_ok();
checks.push(HealthCheckItem {
name: "LLD linker".to_string(),
passed: has_lld,
message: if has_lld {
"LLD found".to_string()
} else {
"LLD not found".to_string()
},
severity: if has_lld {
HealthCheckSeverity::Info
} else {
HealthCheckSeverity::Warning
},
});
let has_cmake = which::which("cmake").is_ok();
checks.push(HealthCheckItem {
name: "CMake".to_string(),
passed: has_cmake,
message: if has_cmake {
"CMake found".to_string()
} else {
"CMake not found".to_string()
},
severity: if has_cmake {
HealthCheckSeverity::Info
} else {
HealthCheckSeverity::Error
},
});
let has_ninja = which::which("ninja").is_ok();
checks.push(HealthCheckItem {
name: "Ninja".to_string(),
passed: has_ninja,
message: if has_ninja {
"Ninja found".to_string()
} else {
"Ninja not found".to_string()
},
severity: if has_ninja {
HealthCheckSeverity::Info
} else {
HealthCheckSeverity::Warning
},
});
if let Ok(output) = Command::new("df").arg("-h").arg(".").output() {
let df = String::from_utf8_lossy(&output.stdout);
let available = df
.lines()
.nth(1)
.map(|l| {
let parts: Vec<&str> = l.split_whitespace().collect();
parts.get(3).map(|s| s.to_string()).unwrap_or_default()
})
.unwrap_or_default();
checks.push(HealthCheckItem {
name: "Disk space".to_string(),
passed: true,
message: format!("Available: {}", available),
severity: HealthCheckSeverity::Info,
});
}
let mem_mb = detect_system_memory_mb();
let mem_ok = mem_mb >= 4096;
checks.push(HealthCheckItem {
name: "System memory".to_string(),
passed: mem_ok,
message: format!(
"{} MB available ({} for heavy builds)",
mem_mb,
if mem_ok { "sufficient" } else { "insufficient" }
),
severity: if mem_ok {
HealthCheckSeverity::Info
} else {
HealthCheckSeverity::Warning
},
});
let all_passed = checks
.iter()
.all(|c| c.passed || c.severity != HealthCheckSeverity::Error);
HealthCheckResult {
all_passed,
checks,
timestamp: SystemTime::now(),
}
}
impl HealthCheckResult {
pub fn print_report(&self) -> String {
let mut report = String::from(
"Build Environment Health Check
",
);
report.push_str(
"================================
",
);
for check in &self.checks {
let icon = if check.passed { "[PASS]" } else { "[FAIL]" };
report.push_str(&format!(
"{} {}: {}
",
icon, check.name, check.message
));
}
report.push_str(&format!(
"
Overall: {}
",
if self.all_passed {
"HEALTHY"
} else {
"ISSUES FOUND"
}
));
report
}
}
pub fn generate_build_script(config: &DeepProjectConfig, registry: &X86ProjectsDeep) -> String {
let mut script = String::from(
"#!/usr/bin/env bash
",
);
script.push_str(
"set -euo pipefail
",
);
script.push_str(&format!(
"# Auto-generated build script for {}
",
config.name
));
script.push_str(&format!(
"# Generated by LLVM-native
"
));
script.push_str(
"export CC=clang
",
);
script.push_str(
"export CXX=clang++
",
);
script.push_str(&format!("export CFLAGS=\"{}\"\n", config.cflags.join(" ")));
script.push_str(&format!(
"export CXXFLAGS=\"{}\"\n",
config.cxxflags.join(" ")
));
script.push_str(&format!(
"export LDFLAGS=\"{}\"\n",
config.ldflags.join(" ")
));
script.push_str(
"
",
);
let source_dir = registry.project_source_dir(config.id);
let build_dir = registry.project_build_dir(config.id, config.stage);
match config.build_system {
DeepBuildSystem::Cmake => {
script.push_str(&format!(
"cmake -G Ninja -S {} -B {}\n
",
source_dir.display(),
build_dir.display()
));
for (key, value) in &config.cmake_vars {
script.push_str(&format!(
" -D{}={} \
",
key, value
));
}
script.push_str(&format!(
"
ninja -C {} -j16
",
build_dir.display()
));
}
DeepBuildSystem::Autotools => {
script.push_str(&format!(
"cd {}
",
source_dir.display()
));
script.push_str("./configure ");
for flag in &config.configure_flags {
script.push_str(&format!("{} ", flag));
}
script.push_str(
"
",
);
script.push_str(
"make -j16
",
);
}
DeepBuildSystem::Kbuild => {
script.push_str(&format!(
"cd {}
",
source_dir.display()
));
script.push_str(
"make defconfig ARCH=x86_64
",
);
script.push_str(
"make -j16 bzImage modules
",
);
}
_ => {
script.push_str(&format!(
"make -C {} -j16
",
source_dir.display()
));
}
}
script.push_str(&format!(
"
echo 'Build of {} completed.'
",
config.name
));
script
}
#[derive(Debug, Clone)]
pub struct BuildSchedule {
pub name: String,
pub projects: Vec<DeepProjectId>,
pub cron_expr: Option<String>,
pub watch_branch: Option<String>,
pub notify: bool,
pub enabled: bool,
pub last_run: Option<SystemTime>,
pub next_run: Option<SystemTime>,
}
impl BuildSchedule {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
projects: Vec::new(),
cron_expr: None,
watch_branch: None,
notify: true,
enabled: true,
last_run: None,
next_run: None,
}
}
pub fn is_due(&self) -> bool {
if !self.enabled {
return false;
}
match self.next_run {
Some(next) => SystemTime::now() >= next,
None => false,
}
}
}
#[derive(Debug, Clone)]
pub struct BuildScheduler {
pub schedules: Vec<BuildSchedule>,
pub registry: Option<Box<X86ProjectsDeep>>,
}
impl BuildScheduler {
pub fn new() -> Self {
Self {
schedules: Vec::new(),
registry: None,
}
}
pub fn add(&mut self, schedule: BuildSchedule) {
self.schedules.push(schedule);
}
pub fn due_schedules(&self) -> Vec<&BuildSchedule> {
self.schedules.iter().filter(|s| s.is_due()).collect()
}
pub fn list_schedules(&self) -> String {
let mut out = String::from(
"Scheduled Builds:
",
);
for s in &self.schedules {
let status = if s.enabled { "enabled" } else { "disabled" };
let cron = s.cron_expr.as_deref().unwrap_or("manual");
let projects: Vec<String> = s.projects.iter().map(|p| p.as_str().to_string()).collect();
out.push_str(&format!(
" {}: [{}] @ {} ({})
",
s.name,
projects.join(", "),
cron,
status
));
}
out
}
}
#[derive(Debug, Clone)]
pub struct BuildMetrics {
pub project_id: DeepProjectId,
pub wall_time_secs: f64,
pub cpu_time_secs: f64,
pub user_time_secs: f64,
pub system_time_secs: f64,
pub max_rss_mb: f64,
pub page_faults: u64,
pub context_switches: u64,
pub io_read_bytes: u64,
pub io_write_bytes: u64,
pub compile_units: usize,
pub link_units: usize,
pub cache_hits: usize,
pub cache_misses: usize,
pub success: bool,
}
impl BuildMetrics {
pub fn throughput_tus_per_sec(&self) -> f64 {
if self.wall_time_secs > 0.0 {
self.compile_units as f64 / self.wall_time_secs
} else {
0.0
}
}
pub fn cache_hit_rate(&self) -> f64 {
let total = self.cache_hits + self.cache_misses;
if total > 0 {
self.cache_hits as f64 / total as f64
} else {
0.0
}
}
pub fn format_summary(&self) -> String {
format!(
"Build Metrics: {}
\n Wall time: {:.1}s | CPU: {:.1}s | Throughput: {:.1} TU/s
\n Memory peak: {:.0} MB | I/O: {:.0} MB read / {:.0} MB written
\n Cache: {:.0}% hit rate ({}/{} hits)",
self.project_id.display_name(),
self.wall_time_secs,
self.cpu_time_secs,
self.throughput_tus_per_sec(),
self.max_rss_mb,
self.io_read_bytes as f64 / 1_048_576.0,
self.io_write_bytes as f64 / 1_048_576.0,
self.cache_hit_rate() * 100.0,
self.cache_hits,
self.cache_hits + self.cache_misses,
)
}
}
#[derive(Debug, Clone)]
pub struct WarningBaseline {
pub project_id: DeepProjectId,
pub warning_count: usize,
pub warning_hashes: HashSet<String>,
pub suppressed_count: usize,
pub created_at: SystemTime,
pub commit: Option<String>,
}
impl WarningBaseline {
pub fn new(project_id: DeepProjectId) -> Self {
Self {
project_id,
warning_count: 0,
warning_hashes: HashSet::new(),
suppressed_count: 0,
created_at: SystemTime::now(),
commit: None,
}
}
pub fn hash_warning(message: &str, file: &str, line: u32) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
message.hash(&mut hasher);
file.hash(&mut hasher);
line.hash(&mut hasher);
format!("{:016x}", hasher.finish())
}
pub fn is_known(&self, hash: &str) -> bool {
self.warning_hashes.contains(hash)
}
pub fn add_warning(&mut self, hash: String) {
self.warning_hashes.insert(hash);
self.warning_count = self.warning_hashes.len();
}
}
pub fn neon_to_sse_mapping_table() -> HashMap<String, String> {
let mut map = HashMap::new();
map.insert("vaddq_f32".into(), "_mm_add_ps".into());
map.insert("vsubq_f32".into(), "_mm_sub_ps".into());
map.insert("vmulq_f32".into(), "_mm_mul_ps".into());
map.insert("vdivq_f32".into(), "_mm_div_ps".into());
map.insert("vaddq_s32".into(), "_mm_add_epi32".into());
map.insert("vsubq_s32".into(), "_mm_sub_epi32".into());
map.insert("vmovq_n_f32".into(), "_mm_set1_ps".into());
map.insert("vld1q_f32".into(), "_mm_loadu_ps".into());
map.insert("vst1q_f32".into(), "_mm_storeu_ps".into());
map.insert("vceqq_f32".into(), "_mm_cmpeq_ps".into());
map.insert("vcgtq_f32".into(), "_mm_cmpgt_ps".into());
map.insert("vcltq_f32".into(), "_mm_cmplt_ps".into());
map.insert("vmaxq_f32".into(), "_mm_max_ps".into());
map.insert("vminq_f32".into(), "_mm_min_ps".into());
map.insert("vsqrtq_f32".into(), "_mm_sqrt_ps".into());
map.insert("vrsqrteq_f32".into(), "_mm_rsqrt_ps".into());
map.insert("vrecpeq_f32".into(), "_mm_rcp_ps".into());
map.insert(
"vabsq_f32".into(),
"_mm_andnot_ps(_mm_set1_ps(-0.0f), a)".into(),
);
map.insert(
"vnegq_f32".into(),
"_mm_xor_ps(a, _mm_set1_ps(-0.0f))".into(),
);
map.insert("vandq_s32".into(), "_mm_and_si128".into());
map.insert("vorrq_s32".into(), "_mm_or_si128".into());
map.insert("veorq_s32".into(), "_mm_xor_si128".into());
map.insert("vshlq_n_s32".into(), "_mm_slli_epi32".into());
map.insert("vshrq_n_s32".into(), "_mm_srai_epi32".into());
map.insert("vreinterpretq_f32_s32".into(), "_mm_castsi128_ps".into());
map.insert("vreinterpretq_s32_f32".into(), "_mm_castps_si128".into());
map
}
pub fn translate_neon_to_sse(neon_code: &str) -> String {
let mapping = neon_to_sse_mapping_table();
let mut result = neon_code.to_string();
for (neon, sse) in &mapping {
result = result.replace(neon, sse);
}
if result.contains("_mm_") && !result.contains("#include <xmmintrin.h>") {
let header = "#include <xmmintrin.h>
#include <emmintrin.h>
";
result.insert_str(0, header);
}
result
}
pub const MIN_CLANG_VERSION: &str = "16.0.0";
pub const DEEP_PROJECT_IDS: &[&str] = &[
"llvm",
"linux-kernel",
"qt",
"boost",
"ffmpeg",
"opencv",
"tensorflow-lite",
"protobuf",
"grpc",
"abseil",
"leveldb",
"rocksdb",
"duckdb",
"clickhouse",
"scylladb",
];
pub const DEFAULT_PARALLEL_LINK_JOBS: usize = 2;
pub const MAX_BUILD_RETRIES: usize = 3;
pub const BUILD_STEP_TIMEOUT_SECS: u64 = 300;
pub const TEST_TIMEOUT_SECS: u64 = 600;
pub const DEFAULT_PGO_TRAINING_ITERS: usize = 5;
pub const BOLT_MODES: &[&str] = &["hfsort", "hfsort+", "cdsplit", "cache+", "stale-matching"];
pub const X86_CMAKE_TOOLCHAIN_TEMPLATE: &str = "cmake/x86-linux-toolchain.cmake";
pub const DEFAULT_TARGET_MICROARCH: &str = "x86-64-v3";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum DeepProjectId {
Llvm,
LinuxKernel,
Qt,
Boost,
Ffmpeg,
OpenCV,
TensorFlowLite,
Protobuf,
Grpc,
Abseil,
LevelDb,
RocksDb,
DuckDb,
ClickHouse,
ScyllaDb,
}
impl DeepProjectId {
pub fn as_str(&self) -> &'static str {
match self {
Self::Llvm => "llvm",
Self::LinuxKernel => "linux-kernel",
Self::Qt => "qt",
Self::Boost => "boost",
Self::Ffmpeg => "ffmpeg",
Self::OpenCV => "opencv",
Self::TensorFlowLite => "tensorflow-lite",
Self::Protobuf => "protobuf",
Self::Grpc => "grpc",
Self::Abseil => "abseil",
Self::LevelDb => "leveldb",
Self::RocksDb => "rocksdb",
Self::DuckDb => "duckdb",
Self::ClickHouse => "clickhouse",
Self::ScyllaDb => "scylladb",
}
}
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"llvm" | "clang" => Some(Self::Llvm),
"linux-kernel" | "linux" => Some(Self::LinuxKernel),
"qt" => Some(Self::Qt),
"boost" => Some(Self::Boost),
"ffmpeg" => Some(Self::Ffmpeg),
"opencv" => Some(Self::OpenCV),
"tensorflow-lite" | "tflite" => Some(Self::TensorFlowLite),
"protobuf" | "protocol-buffers" => Some(Self::Protobuf),
"grpc" => Some(Self::Grpc),
"abseil" | "absl" => Some(Self::Abseil),
"leveldb" => Some(Self::LevelDb),
"rocksdb" => Some(Self::RocksDb),
"duckdb" => Some(Self::DuckDb),
"clickhouse" => Some(Self::ClickHouse),
"scylladb" | "seastar" => Some(Self::ScyllaDb),
_ => None,
}
}
pub fn display_name(&self) -> &'static str {
match self {
Self::Llvm => "LLVM/Clang",
Self::LinuxKernel => "Linux Kernel",
Self::Qt => "Qt Framework",
Self::Boost => "Boost C++ Libraries",
Self::Ffmpeg => "FFmpeg",
Self::OpenCV => "OpenCV",
Self::TensorFlowLite => "TensorFlow Lite",
Self::Protobuf => "Protocol Buffers",
Self::Grpc => "gRPC",
Self::Abseil => "Abseil",
Self::LevelDb => "LevelDB",
Self::RocksDb => "RocksDB",
Self::DuckDb => "DuckDB",
Self::ClickHouse => "ClickHouse",
Self::ScyllaDb => "ScyllaDB/Seastar",
}
}
}
impl fmt::Display for DeepProjectId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepBuildVariant {
Debug,
Release,
RelWithDebInfo,
MinSizeRel,
PgoInstrumented,
PgoOptimized,
Sanitized,
Fuzz,
Coverage,
Custom,
}
impl DeepBuildVariant {
pub fn as_cmake_build_type(&self) -> Option<&'static str> {
match self {
Self::Debug => Some("Debug"),
Self::Release => Some("Release"),
Self::RelWithDebInfo => Some("RelWithDebInfo"),
Self::MinSizeRel => Some("MinSizeRel"),
_ => None, }
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Debug => "debug",
Self::Release => "release",
Self::RelWithDebInfo => "relwithdebinfo",
Self::MinSizeRel => "minsizerel",
Self::PgoInstrumented => "pgo-instrumented",
Self::PgoOptimized => "pgo-optimized",
Self::Sanitized => "sanitized",
Self::Fuzz => "fuzz",
Self::Coverage => "coverage",
Self::Custom => "custom",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum DeepBuildStage {
Stage0,
Stage1,
Stage2,
Stage3,
Single,
}
impl DeepBuildStage {
pub fn index(&self) -> u32 {
match self {
Self::Stage0 => 0,
Self::Stage1 => 1,
Self::Stage2 => 2,
Self::Stage3 => 3,
Self::Single => 0,
}
}
pub fn is_bootstrap(&self) -> bool {
matches!(
self,
Self::Stage0 | Self::Stage1 | Self::Stage2 | Self::Stage3
) && *self != Self::Single
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum DeepSimdLevel {
None,
Mmx,
Sse,
Sse2,
Sse3,
Ssse3,
Sse41,
Sse42,
Avx,
Avx2,
Avx512F,
Avx512Full,
}
impl DeepSimdLevel {
pub fn to_march_flag(&self) -> Option<&'static str> {
match self {
Self::None => None,
Self::Mmx => Some("pentium-mmx"),
Self::Sse => Some("pentium3"),
Self::Sse2 => Some("pentium4"),
Self::Sse3 => Some("prescott"),
Self::Ssse3 => Some("core2"),
Self::Sse41 => Some("penryn"),
Self::Sse42 => Some("nehalem"),
Self::Avx => Some("sandybridge"),
Self::Avx2 => Some("haswell"),
Self::Avx512F => Some("skylake-avx512"),
Self::Avx512Full => Some("icelake-server"),
}
}
pub fn to_gcc_target_flag(&self) -> Option<&'static str> {
match self {
Self::None => None,
Self::Mmx => None,
Self::Sse => None,
Self::Sse2 => None,
Self::Sse3 => Some("sse3"),
Self::Ssse3 => Some("ssse3"),
Self::Sse41 => Some("sse4.1"),
Self::Sse42 => Some("sse4.2"),
Self::Avx => Some("avx"),
Self::Avx2 => Some("avx2"),
Self::Avx512F => Some("avx512f"),
Self::Avx512Full => Some("avx512f,avx512bw,avx512dq,avx512vl,avx512cd"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeepBuildStatus {
Pending,
Configuring,
Building,
Success,
Failed,
Skipped,
Cancelled,
}
impl DeepBuildStatus {
pub fn is_terminal(&self) -> bool {
matches!(
self,
Self::Success | Self::Failed | Self::Skipped | Self::Cancelled
)
}
pub fn is_running(&self) -> bool {
matches!(self, Self::Configuring | Self::Building)
}
}
impl fmt::Display for DeepBuildStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Pending => write!(f, "pending"),
Self::Configuring => write!(f, "configuring"),
Self::Building => write!(f, "building"),
Self::Success => write!(f, "success"),
Self::Failed => write!(f, "failed"),
Self::Skipped => write!(f, "skipped"),
Self::Cancelled => write!(f, "cancelled"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepSanitizer {
Address,
Undefined,
Memory,
Thread,
Leak,
HwAddress,
AddressUndefined,
}
impl DeepSanitizer {
pub fn to_cflag(&self) -> &'static str {
match self {
Self::Address => "-fsanitize=address",
Self::Undefined => "-fsanitize=undefined",
Self::Memory => "-fsanitize=memory",
Self::Thread => "-fsanitize=thread",
Self::Leak => "-fsanitize=leak",
Self::HwAddress => "-fsanitize=hwaddress",
Self::AddressUndefined => "-fsanitize=address,undefined",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepCompressionBackend {
None,
Zlib,
Zstd,
Lz4,
Snappy,
Bzip2,
Brotli,
Xz,
}
impl DeepCompressionBackend {
pub fn cmake_var(&self) -> &'static str {
match self {
Self::None => "OFF",
Self::Zlib => "WITH_ZLIB",
Self::Zstd => "WITH_ZSTD",
Self::Lz4 => "WITH_LZ4",
Self::Snappy => "WITH_SNAPPY",
Self::Bzip2 => "WITH_BZIP2",
Self::Brotli => "WITH_BROTLI",
Self::Xz => "WITH_LZMA",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepSslBackend {
OpenSsl,
BoringSsl,
LibreSsl,
None,
}
impl DeepSslBackend {
pub fn cmake_var(&self) -> &'static str {
match self {
Self::OpenSsl => "OPENSSL_ROOT_DIR",
Self::BoringSsl => "BORINGSSL_ROOT_DIR",
Self::LibreSsl => "LIBRESSL_ROOT_DIR",
Self::None => "",
}
}
}
#[derive(Debug, Clone)]
pub struct X86ProjectsDeep {
pub projects_root: PathBuf,
pub build_root: PathBuf,
pub install_prefix: PathBuf,
pub target_triple: String,
pub target_cpu: String,
pub target_features: Vec<String>,
pub opt_level: X86OptLevel,
pub parallel_jobs: usize,
pub parallel_link_jobs: usize,
pub verbose: bool,
pub use_ccache: bool,
pub use_distcc: bool,
pub projects: BTreeMap<DeepProjectId, DeepProjectConfig>,
pub build: Option<X86ProjectBuild>,
pub test: Option<X86ProjectTest>,
pub optimize: Option<X86ProjectOptimize>,
pub results: BTreeMap<DeepProjectId, DeepBuildReport>,
pub env: HashMap<String, String>,
pub global_cmake_vars: HashMap<String, String>,
pub extra_cflags: Vec<String>,
pub extra_cxxflags: Vec<String>,
pub extra_ldflags: Vec<String>,
pub system_deps: HashSet<String>,
pub stop_on_error: bool,
}
impl X86ProjectsDeep {
pub fn new(projects_root: &Path) -> Self {
let projects_root = projects_root.to_path_buf();
let build_root = projects_root.join("build").join("x86-deep");
let install_prefix = projects_root.join("install").join("x86-deep");
let mut env = HashMap::new();
env.insert("CC".to_string(), "clang".to_string());
env.insert("CXX".to_string(), "clang++".to_string());
env.insert("LD".to_string(), "lld".to_string());
env.insert("AR".to_string(), "llvm-ar".to_string());
env.insert("NM".to_string(), "llvm-nm".to_string());
env.insert("RANLIB".to_string(), "llvm-ranlib".to_string());
env.insert("STRIP".to_string(), "llvm-strip".to_string());
env.insert("OBJCOPY".to_string(), "llvm-objcopy".to_string());
env.insert("OBJDUMP".to_string(), "llvm-objdump".to_string());
Self {
projects_root,
build_root,
install_prefix,
target_triple: X86_64_LINUX_TRIPLE.to_string(),
target_cpu: "x86-64-v3".to_string(),
target_features: vec!["sse2".into(), "avx2".into()],
opt_level: X86OptLevel::O2,
parallel_jobs: DEFAULT_PARALLEL_JOBS,
parallel_link_jobs: DEFAULT_PARALLEL_LINK_JOBS,
verbose: false,
use_ccache: true,
use_distcc: false,
projects: BTreeMap::new(),
build: None,
test: None,
optimize: None,
results: BTreeMap::new(),
env,
global_cmake_vars: HashMap::new(),
extra_cflags: vec!["-march=x86-64-v3".into(), "-mtune=generic".into()],
extra_cxxflags: vec!["-march=x86-64-v3".into(), "-mtune=generic".into()],
extra_ldflags: vec!["-fuse-ld=lld".into()],
system_deps: HashSet::new(),
stop_on_error: true,
}
}
pub fn register(&mut self, config: DeepProjectConfig) {
self.projects.insert(config.id, config);
}
pub fn register_all(&mut self, configs: Vec<DeepProjectConfig>) {
for config in configs {
self.register(config);
}
}
pub fn get_project(&self, id: DeepProjectId) -> Option<&DeepProjectConfig> {
self.projects.get(&id)
}
pub fn get_project_mut(&mut self, id: DeepProjectId) -> Option<&mut DeepProjectConfig> {
self.projects.get_mut(&id)
}
pub fn project_build_dir(&self, id: DeepProjectId, stage: DeepBuildStage) -> PathBuf {
let stage_str = match stage {
DeepBuildStage::Stage0 => "stage0",
DeepBuildStage::Stage1 => "stage1",
DeepBuildStage::Stage2 => "stage2",
DeepBuildStage::Stage3 => "stage3",
DeepBuildStage::Single => "single",
};
self.build_root.join(id.as_str()).join(stage_str)
}
pub fn project_install_dir(&self, id: DeepProjectId) -> PathBuf {
self.install_prefix.join(id.as_str())
}
pub fn project_source_dir(&self, id: DeepProjectId) -> PathBuf {
self.projects_root.join(id.as_str())
}
pub fn init_subsystems(&mut self) {
self.build = Some(X86ProjectBuild::new(self));
self.test = Some(X86ProjectTest::new(self));
self.optimize = Some(X86ProjectOptimize::new(self));
}
pub fn generate_toolchain_file(&self) -> String {
let mut toolchain = String::new();
toolchain.push_str(&format!(
"# Auto-generated X86 toolchain file by LLVM-native\n\
set(CMAKE_SYSTEM_NAME Linux)\n\
set(CMAKE_SYSTEM_PROCESSOR {})\n\
set(CMAKE_C_COMPILER clang)\n\
set(CMAKE_CXX_COMPILER clang++)\n\
set(CMAKE_C_COMPILER_TARGET {})\n\
set(CMAKE_CXX_COMPILER_TARGET {})\n\
set(CMAKE_ASM_COMPILER_TARGET {})\n\
set(CMAKE_C_FLAGS \"{}\" CACHE STRING \"\")\n\
set(CMAKE_CXX_FLAGS \"{}\" CACHE STRING \"\")\n\
set(CMAKE_EXE_LINKER_FLAGS \"{}\" CACHE STRING \"\")\n\
set(CMAKE_SHARED_LINKER_FLAGS \"{}\" CACHE STRING \"\")\n",
self.target_cpu,
self.target_triple,
self.target_triple,
self.target_triple,
self.extra_cflags.join(" "),
self.extra_cxxflags.join(" "),
self.extra_ldflags.join(" "),
self.extra_ldflags.join(" "),
));
if self.use_ccache {
toolchain.push_str("set(CMAKE_C_COMPILER_LAUNCHER ccache)\n");
toolchain.push_str("set(CMAKE_CXX_COMPILER_LAUNCHER ccache)\n");
}
toolchain
}
pub fn write_toolchain_file(&self, path: &Path) -> io::Result<()> {
let content = self.generate_toolchain_file();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(path, content)
}
pub fn register_default_projects(&mut self) {
self.register(llvm_deep_config());
self.register(linux_kernel_deep_config());
self.register(qt_deep_config());
self.register(boost_deep_config());
self.register(ffmpeg_deep_config());
self.register(opencv_deep_config());
self.register(tensorflow_lite_deep_config());
self.register(protobuf_deep_config());
self.register(grpc_deep_config());
self.register(abseil_deep_config());
self.register(leveldb_deep_config());
self.register(rocksdb_deep_config());
self.register(duckdb_deep_config());
self.register(clickhouse_deep_config());
self.register(scylladb_deep_config());
}
pub fn build_order(&self) -> Vec<DeepProjectId> {
let mut order = Vec::new();
let mut visited = HashSet::new();
let mut visiting = HashSet::new();
for &id in self.projects.keys() {
if !visited.contains(&id) {
self.topological_visit(id, &mut visited, &mut visiting, &mut order);
}
}
order.reverse();
order
}
fn topological_visit(
&self,
id: DeepProjectId,
visited: &mut HashSet<DeepProjectId>,
visiting: &mut HashSet<DeepProjectId>,
order: &mut Vec<DeepProjectId>,
) {
if visited.contains(&id) {
return;
}
if visiting.contains(&id) {
return;
}
visiting.insert(id);
if let Some(config) = self.projects.get(&id) {
for dep in &config.dependencies {
self.topological_visit(*dep, visited, visiting, order);
}
}
visiting.remove(&id);
visited.insert(id);
order.push(id);
}
pub fn validate_dependencies(&self) -> Vec<String> {
let mut issues = Vec::new();
let registered: HashSet<DeepProjectId> = self.projects.keys().copied().collect();
for (id, config) in &self.projects {
for dep in &config.dependencies {
if !registered.contains(dep) && !self.system_deps.contains(dep.as_str()) {
issues.push(format!(
"{} depends on {} which is not registered or installed",
id.display_name(),
dep.display_name(),
));
}
}
}
issues
}
}
#[derive(Debug, Clone)]
pub struct DeepProjectConfig {
pub id: DeepProjectId,
pub name: String,
pub version: String,
pub repo_url: String,
pub source_subdir: String,
pub build_system: DeepBuildSystem,
pub variant: DeepBuildVariant,
pub stage: DeepBuildStage,
pub supports_bootstrap: bool,
pub dependencies: Vec<DeepProjectId>,
pub cmake_vars: HashMap<String, String>,
pub configure_flags: Vec<String>,
pub meson_options: Vec<String>,
pub bazel_flags: Vec<String>,
pub env_overrides: HashMap<String, String>,
pub patches: Vec<DeepPatch>,
pub exclude_sources: Vec<String>,
pub extra_sources: Vec<PathBuf>,
pub defines: Vec<(String, Option<String>)>,
pub includes: Vec<PathBuf>,
pub libraries: Vec<String>,
pub lib_dirs: Vec<PathBuf>,
pub cflags: Vec<String>,
pub cxxflags: Vec<String>,
pub ldflags: Vec<String>,
pub simd_level: DeepSimdLevel,
pub enable_lto: bool,
pub enable_pgo: bool,
pub pgo_training_cmd: Option<String>,
pub test_config: Option<DeepTestConfig>,
pub opt_config: Option<DeepOptConfig>,
}
impl DeepProjectConfig {
pub fn new(id: DeepProjectId) -> Self {
Self {
id,
name: id.display_name().to_string(),
version: "main".to_string(),
repo_url: String::new(),
source_subdir: id.as_str().to_string(),
build_system: DeepBuildSystem::Cmake,
variant: DeepBuildVariant::Release,
stage: DeepBuildStage::Single,
supports_bootstrap: false,
dependencies: Vec::new(),
cmake_vars: HashMap::new(),
configure_flags: Vec::new(),
meson_options: Vec::new(),
bazel_flags: Vec::new(),
env_overrides: HashMap::new(),
patches: Vec::new(),
exclude_sources: Vec::new(),
extra_sources: Vec::new(),
defines: Vec::new(),
includes: Vec::new(),
libraries: Vec::new(),
lib_dirs: Vec::new(),
cflags: Vec::new(),
cxxflags: Vec::new(),
ldflags: Vec::new(),
simd_level: DeepSimdLevel::Sse2,
enable_lto: false,
enable_pgo: false,
pgo_training_cmd: None,
test_config: None,
opt_config: None,
}
}
pub fn cflags_str(&self) -> String {
self.cflags.join(" ")
}
pub fn cxxflags_str(&self) -> String {
self.cxxflags.join(" ")
}
pub fn ldflags_str(&self) -> String {
self.ldflags.join(" ")
}
pub fn cmake_var(mut self, key: &str, value: &str) -> Self {
self.cmake_vars.insert(key.to_string(), value.to_string());
self
}
pub fn configure_flag(mut self, flag: &str) -> Self {
self.configure_flags.push(flag.to_string());
self
}
pub fn depends_on(mut self, dep: DeepProjectId) -> Self {
self.dependencies.push(dep);
self
}
pub fn with_variant(mut self, variant: DeepBuildVariant) -> Self {
self.variant = variant;
self
}
pub fn with_lto(mut self) -> Self {
self.enable_lto = true;
self
}
pub fn with_simd(mut self, level: DeepSimdLevel) -> Self {
self.simd_level = level;
self
}
pub fn cflag(mut self, flag: &str) -> Self {
self.cflags.push(flag.to_string());
self
}
pub fn cxxflag(mut self, flag: &str) -> Self {
self.cxxflags.push(flag.to_string());
self
}
pub fn ldflag(mut self, flag: &str) -> Self {
self.ldflags.push(flag.to_string());
self
}
pub fn define(mut self, name: &str, value: Option<&str>) -> Self {
self.defines
.push((name.to_string(), value.map(|v| v.to_string())));
self
}
pub fn patch(mut self, patch: DeepPatch) -> Self {
self.patches.push(patch);
self
}
}
impl Default for DeepProjectConfig {
fn default() -> Self {
Self::new(DeepProjectId::Llvm)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepBuildSystem {
Cmake,
Make,
Autotools,
Meson,
Bazel,
BoostBuild,
QMake,
Kbuild,
Ninja,
Custom,
}
impl DeepBuildSystem {
pub fn as_str(&self) -> &'static str {
match self {
Self::Cmake => "cmake",
Self::Make => "make",
Self::Autotools => "autotools",
Self::Meson => "meson",
Self::Bazel => "bazel",
Self::BoostBuild => "boost-build",
Self::QMake => "qmake",
Self::Kbuild => "kbuild",
Self::Ninja => "ninja",
Self::Custom => "custom",
}
}
}
#[derive(Debug, Clone)]
pub struct DeepPatch {
pub description: String,
pub target_file: String,
pub find_content: Option<String>,
pub replace_content: Option<String>,
pub is_diff_file: bool,
pub patch_file_path: Option<PathBuf>,
pub required: bool,
pub line_range: Option<(usize, usize)>,
}
impl DeepPatch {
pub fn new_inline(description: &str, target_file: &str, find: &str, replace: &str) -> Self {
Self {
description: description.to_string(),
target_file: target_file.to_string(),
find_content: Some(find.to_string()),
replace_content: Some(replace.to_string()),
is_diff_file: false,
patch_file_path: None,
required: true,
line_range: None,
}
}
pub fn new_diff(description: &str, target_file: &str, patch_path: &Path) -> Self {
Self {
description: description.to_string(),
target_file: target_file.to_string(),
find_content: None,
replace_content: None,
is_diff_file: true,
patch_file_path: Some(patch_path.to_path_buf()),
required: true,
line_range: None,
}
}
pub fn apply(&self, source_root: &Path) -> io::Result<bool> {
if self.is_diff_file {
self.apply_diff_file(source_root)
} else {
self.apply_inline(source_root)
}
}
fn apply_inline(&self, source_root: &Path) -> io::Result<bool> {
let file_path = source_root.join(&self.target_file);
if !file_path.exists() {
if self.required {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Patch target file not found: {}", file_path.display()),
));
}
return Ok(false);
}
let content = fs::read_to_string(&file_path)?;
let find = self.find_content.as_deref().unwrap_or("");
let replace = self.replace_content.as_deref().unwrap_or("");
if let Some(new_content) = self.apply_line_range_patch(&content, find, replace) {
fs::write(&file_path, new_content)?;
return Ok(true);
}
if content.contains(find) {
let new_content = content.replace(find, replace);
fs::write(&file_path, new_content)?;
Ok(true)
} else {
if self.required {
Err(io::Error::new(
io::ErrorKind::Other,
format!(
"Could not find patch target in {}: {}",
self.target_file, self.description
),
))
} else {
Ok(false)
}
}
}
fn apply_line_range_patch(&self, content: &str, find: &str, replace: &str) -> Option<String> {
let (start, end) = self.line_range?;
let lines: Vec<&str> = content.lines().collect();
if start == 0 || end == 0 || start > lines.len() || end > lines.len() {
return None;
}
let region: String = lines[(start - 1)..end].join("\n");
if region.contains(find) {
let new_region = region.replace(find, replace);
let mut new_lines: Vec<String> = lines.iter().map(|s| s.to_string()).collect();
let new_region_lines: Vec<&str> = new_region.lines().collect();
for (i, line) in new_region_lines.iter().enumerate() {
if start - 1 + i < new_lines.len() {
new_lines[start - 1 + i] = line.to_string();
}
}
Some(new_lines.join("\n"))
} else {
None
}
}
fn apply_diff_file(&self, source_root: &Path) -> io::Result<bool> {
let patch_path = match &self.patch_file_path {
Some(p) => p.clone(),
None => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Diff patch specified but no patch file path provided",
));
}
};
if !patch_path.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Patch file not found: {}", patch_path.display()),
));
}
let output = Command::new("patch")
.arg("-p1")
.arg("-d")
.arg(source_root)
.arg("-i")
.arg(&patch_path)
.output()?;
Ok(output.status.success())
}
}
#[derive(Debug, Clone)]
pub struct DeepBuildReport {
pub project_id: DeepProjectId,
pub status: DeepBuildStatus,
pub start_time: Option<SystemTime>,
pub end_time: Option<SystemTime>,
pub duration: Duration,
pub tus_compiled: usize,
pub tus_failed: usize,
pub link_steps: usize,
pub link_steps_failed: usize,
pub output_size_bytes: u64,
pub warning_count: usize,
pub error_count: usize,
pub diagnostics: Vec<DeepBuildDiagnostic>,
pub stage_results: HashMap<DeepBuildStage, DeepStageReport>,
pub test_report: Option<DeepTestReport>,
pub opt_report: Option<DeepOptimizationReport>,
pub log_file: Option<PathBuf>,
pub cdb_path: Option<PathBuf>,
pub metadata: HashMap<String, String>,
}
impl DeepBuildReport {
pub fn new(project_id: DeepProjectId) -> Self {
Self {
project_id,
status: DeepBuildStatus::Pending,
start_time: None,
end_time: None,
duration: Duration::ZERO,
tus_compiled: 0,
tus_failed: 0,
link_steps: 0,
link_steps_failed: 0,
output_size_bytes: 0,
warning_count: 0,
error_count: 0,
diagnostics: Vec::new(),
stage_results: HashMap::new(),
test_report: None,
opt_report: None,
log_file: None,
cdb_path: None,
metadata: HashMap::new(),
}
}
pub fn is_success(&self) -> bool {
self.status == DeepBuildStatus::Success
}
pub fn elapsed(&self) -> Duration {
match (self.start_time, self.end_time) {
(Some(start), Some(end)) => end.duration_since(start).unwrap_or(Duration::ZERO),
_ => self.duration,
}
}
pub fn summary(&self) -> String {
format!(
"{}: {} ({} TUs, {} warnings, {} errors, {:.1}s)",
self.project_id.display_name(),
self.status,
self.tus_compiled,
self.warning_count,
self.error_count,
self.elapsed().as_secs_f64(),
)
}
pub fn to_json(&self) -> String {
let mut json = format!(
"{{\"project\":\"{}\",\"status\":\"{}\",\"tus_compiled\":{},\"tus_failed\":{},\
\"warnings\":{},\"errors\":{},\"duration_secs\":{:.3},\"output_size_bytes\":{}}}",
self.project_id.as_str(),
self.status,
self.tus_compiled,
self.tus_failed,
self.warning_count,
self.error_count,
self.elapsed().as_secs_f64(),
self.output_size_bytes,
);
json
}
}
#[derive(Debug, Clone)]
pub struct DeepStageReport {
pub stage: DeepBuildStage,
pub status: DeepBuildStatus,
pub tus_compiled: usize,
pub duration: Duration,
pub compiler_hash: Option<String>,
pub comparison_passed: Option<bool>,
}
impl DeepStageReport {
pub fn new(stage: DeepBuildStage) -> Self {
Self {
stage,
status: DeepBuildStatus::Pending,
tus_compiled: 0,
duration: Duration::ZERO,
compiler_hash: None,
comparison_passed: None,
}
}
}
#[derive(Debug, Clone)]
pub struct DeepBuildDiagnostic {
pub severity: X86DiagLevel,
pub message: String,
pub file: Option<PathBuf>,
pub line: Option<u32>,
pub column: Option<u32>,
pub build_step: String,
pub is_known_issue: bool,
}
#[derive(Debug, Clone)]
pub struct DeepTestConfig {
pub run_after_build: bool,
pub test_framework: DeepTestFramework,
pub test_command: String,
pub test_dir: PathBuf,
pub timeout_secs: u64,
pub filter: Option<String>,
pub exclude_filter: Option<String>,
pub parallel: bool,
pub parallel_workers: usize,
pub output_format: DeepTestOutputFormat,
pub baseline_path: Option<PathBuf>,
pub max_regression_pct: f64,
pub benchmark_config: Option<DeepBenchmarkConfig>,
}
impl Default for DeepTestConfig {
fn default() -> Self {
Self {
run_after_build: true,
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure".to_string(),
test_dir: PathBuf::from("build"),
timeout_secs: TEST_TIMEOUT_SECS,
filter: None,
exclude_filter: None,
parallel: true,
parallel_workers: 0, output_format: DeepTestOutputFormat::JunitXml,
baseline_path: None,
max_regression_pct: 5.0,
benchmark_config: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeepTestFramework {
Ctest,
GTest,
BoostTest,
Catch2,
PythonUnittest,
ShellScript,
MakeCheck,
Custom,
}
impl DeepTestFramework {
pub fn as_str(&self) -> &'static str {
match self {
Self::Ctest => "ctest",
Self::GTest => "gtest",
Self::BoostTest => "boost_test",
Self::Catch2 => "catch2",
Self::PythonUnittest => "python_unittest",
Self::ShellScript => "shell_script",
Self::MakeCheck => "make_check",
Self::Custom => "custom",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeepTestOutputFormat {
CtestDefault,
JunitXml,
Json,
Tap,
Custom,
}
#[derive(Debug, Clone)]
pub struct DeepBenchmarkConfig {
pub framework: String,
pub command: String,
pub iterations: usize,
pub min_time_secs: f64,
pub compare_baseline: bool,
pub baseline_path: Option<PathBuf>,
}
impl Default for DeepBenchmarkConfig {
fn default() -> Self {
Self {
framework: "google_benchmark".to_string(),
command: "".to_string(),
iterations: 5,
min_time_secs: 1.0,
compare_baseline: true,
baseline_path: None,
}
}
}
#[derive(Debug, Clone)]
pub struct DeepTestReport {
pub project_id: DeepProjectId,
pub all_passed: bool,
pub suites: usize,
pub total: usize,
pub passed: usize,
pub failed: usize,
pub skipped: usize,
pub flaky: usize,
pub duration: Duration,
pub cases: Vec<DeepTestCase>,
pub benchmarks: Vec<DeepBenchmarkResult>,
pub regressions: Vec<DeepTestRegression>,
pub raw_output: String,
}
impl DeepTestReport {
pub fn new(project_id: DeepProjectId) -> Self {
Self {
project_id,
all_passed: false,
suites: 0,
total: 0,
passed: 0,
failed: 0,
skipped: 0,
flaky: 0,
duration: Duration::ZERO,
cases: Vec::new(),
benchmarks: Vec::new(),
regressions: Vec::new(),
raw_output: String::new(),
}
}
pub fn pass_rate(&self) -> f64 {
if self.total == 0 {
1.0
} else {
self.passed as f64 / self.total as f64
}
}
pub fn summary(&self) -> String {
format!(
"{}: {}/{} passed, {} failed, {} skipped ({:.1}s)",
self.project_id.display_name(),
self.passed,
self.total,
self.failed,
self.skipped,
self.duration.as_secs_f64(),
)
}
}
#[derive(Debug, Clone)]
pub struct DeepTestCase {
pub suite: String,
pub name: String,
pub passed: bool,
pub duration: Duration,
pub failure_message: Option<String>,
pub output: String,
pub tags: Vec<String>,
pub is_flaky: bool,
pub skipped: bool,
}
#[derive(Debug, Clone)]
pub struct DeepBenchmarkResult {
pub name: String,
pub iterations: usize,
pub real_time_ns: u64,
pub cpu_time_ns: u64,
pub bytes_processed: u64,
pub items_processed: u64,
pub baseline_time_ns: Option<u64>,
pub delta_pct: Option<f64>,
pub is_regression: bool,
}
#[derive(Debug, Clone)]
pub struct DeepTestRegression {
pub test_name: String,
pub previous_status: String,
pub current_status: String,
pub details: String,
}
#[derive(Debug, Clone)]
pub struct DeepOptConfig {
pub enable_pgo: bool,
pub pgo_training_cmd: Option<String>,
pub pgo_training_iters: usize,
pub pgo_profile_dir: Option<PathBuf>,
pub use_cs_pgo: bool,
pub enable_thin_lto: bool,
pub enable_full_lto: bool,
pub lto_jobs: usize,
pub enable_bolt: bool,
pub bolt_profile: Option<PathBuf>,
pub bolt_mode: String,
pub enable_fmv: bool,
pub fmv_targets: Vec<String>,
pub strip_debug: bool,
pub custom_opt_flags: Vec<String>,
}
impl Default for DeepOptConfig {
fn default() -> Self {
Self {
enable_pgo: false,
pgo_training_cmd: None,
pgo_training_iters: DEFAULT_PGO_TRAINING_ITERS,
pgo_profile_dir: None,
use_cs_pgo: false,
enable_thin_lto: false,
enable_full_lto: false,
lto_jobs: 4,
enable_bolt: false,
bolt_profile: None,
bolt_mode: "hfsort".to_string(),
enable_fmv: false,
fmv_targets: vec![
"x86-64".to_string(),
"x86-64-v2".to_string(),
"x86-64-v3".to_string(),
"x86-64-v4".to_string(),
],
strip_debug: true,
custom_opt_flags: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct DeepOptimizationReport {
pub project_id: DeepProjectId,
pub pgo_applied: bool,
pub pgo_speedup_pct: Option<f64>,
pub lto_applied: bool,
pub lto_size_reduction_pct: Option<f64>,
pub bolt_applied: bool,
pub bolt_speedup_pct: Option<f64>,
pub fmv_applied: bool,
pub fmv_variant_count: usize,
pub binary_size_bytes: u64,
pub binary_size_before_bytes: u64,
pub passes: Vec<DeepOptPass>,
pub duration: Duration,
}
impl DeepOptimizationReport {
pub fn new(project_id: DeepProjectId) -> Self {
Self {
project_id,
pgo_applied: false,
pgo_speedup_pct: None,
lto_applied: false,
lto_size_reduction_pct: None,
bolt_applied: false,
bolt_speedup_pct: None,
fmv_applied: false,
fmv_variant_count: 0,
binary_size_bytes: 0,
binary_size_before_bytes: 0,
passes: Vec::new(),
duration: Duration::ZERO,
}
}
pub fn summary(&self) -> String {
let mut s = format!("{} optimizations:", self.project_id.display_name());
if self.pgo_applied {
s.push_str(&format!(
" PGO(+{:.1}%)",
self.pgo_speedup_pct.unwrap_or(0.0)
));
}
if self.lto_applied {
s.push_str(&format!(
" LTO(-{:.1}% size)",
self.lto_size_reduction_pct.unwrap_or(0.0)
));
}
if self.bolt_applied {
s.push_str(&format!(
" BOLT(+{:.1}%)",
self.bolt_speedup_pct.unwrap_or(0.0)
));
}
if self.fmv_applied {
s.push_str(&format!(" FMV({} variants)", self.fmv_variant_count));
}
s
}
}
#[derive(Debug, Clone)]
pub struct DeepOptPass {
pub name: String,
pub enabled: bool,
pub effect: String,
pub speedup_pct: Option<f64>,
pub size_change_pct: Option<f64>,
}
#[derive(Debug, Clone)]
pub struct X86ProjectBuild {
pub build_root: PathBuf,
pub incremental: bool,
pub clean_build: bool,
pub cache: DeepBuildCache,
pub cdb_config: DeepCdbConfig,
pub build_graph: Vec<DeepBuildStep>,
pub active_builds: HashSet<DeepProjectId>,
pub cancelled: Arc<AtomicBool>,
pub auto_patch: bool,
pub max_concurrent_projects: usize,
pub event_log: Vec<DeepBuildEvent>,
}
impl X86ProjectBuild {
pub fn new(registry: &X86ProjectsDeep) -> Self {
Self {
build_root: registry.build_root.clone(),
incremental: true,
clean_build: false,
cache: DeepBuildCache::new(®istry.build_root.join("cache")),
cdb_config: DeepCdbConfig::default(),
build_graph: Vec::new(),
active_builds: HashSet::new(),
cancelled: Arc::new(AtomicBool::new(false)),
auto_patch: true,
max_concurrent_projects: 4,
event_log: Vec::new(),
}
}
pub fn resolve_build_order(&mut self, registry: &X86ProjectsDeep) -> Vec<DeepProjectId> {
let order = registry.build_order();
self.build_graph = order
.iter()
.map(|id| DeepBuildStep {
project_id: *id,
stage: DeepBuildStage::Single,
step_type: DeepBuildStepType::Compile,
status: DeepBuildStatus::Pending,
dependencies: Vec::new(),
output_paths: Vec::new(),
retry_count: 0,
max_retries: MAX_BUILD_RETRIES,
})
.collect();
order
}
pub fn apply_patches(
&self,
config: &DeepProjectConfig,
source_root: &Path,
) -> io::Result<usize> {
let mut applied = 0;
for patch in &config.patches {
match patch.apply(source_root) {
Ok(true) => {
applied += 1;
log_event(
&mut self.event_log.clone(),
DeepBuildEvent {
project_id: config.id,
event_type: DeepBuildEventType::PatchApplied,
message: format!("Applied patch: {}", patch.description),
timestamp: SystemTime::now(),
duration: None,
},
);
}
Ok(false) => {
log_event(
&mut self.event_log.clone(),
DeepBuildEvent {
project_id: config.id,
event_type: DeepBuildEventType::PatchSkipped,
message: format!("Patch not needed: {}", patch.description),
timestamp: SystemTime::now(),
duration: None,
},
);
}
Err(e) => {
let msg = format!("Failed to apply patch '{}': {}", patch.description, e);
log_event(
&mut self.event_log.clone(),
DeepBuildEvent {
project_id: config.id,
event_type: DeepBuildEventType::Error,
message: msg.clone(),
timestamp: SystemTime::now(),
duration: None,
},
);
if patch.required {
return Err(io::Error::new(io::ErrorKind::Other, msg));
}
}
}
}
Ok(applied)
}
pub fn generate_compilation_db(
&self,
config: &DeepProjectConfig,
build_dir: &Path,
) -> io::Result<PathBuf> {
let cdb_path = build_dir.join("compile_commands.json");
match config.build_system {
DeepBuildSystem::Cmake => {
let mut cmd = Command::new("cmake");
cmd.arg("-DCMAKE_EXPORT_COMPILE_COMMANDS=ON");
cmd.arg(build_dir);
let output = cmd.output()?;
if !output.status.success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"CMake CDB generation failed: {}",
String::from_utf8_lossy(&output.stderr)
),
));
}
}
DeepBuildSystem::Make => {
let result = Command::new("compiledb")
.arg("-n")
.arg("make")
.arg("-o")
.arg(&cdb_path)
.current_dir(build_dir)
.output();
if result.is_err() {
let _ = Command::new("bear")
.arg("--output")
.arg(&cdb_path)
.arg("--")
.arg("make")
.current_dir(build_dir)
.output();
}
}
DeepBuildSystem::Meson => {
let _ = Command::new("meson")
.arg("compile")
.arg("-C")
.arg(build_dir)
.output();
}
DeepBuildSystem::Bazel => {
let _ = Command::new("bazel")
.arg("run")
.arg("@hedron_compile_commands//:refresh_all")
.current_dir(build_dir)
.output();
}
_ => {
}
}
Ok(cdb_path)
}
pub fn needs_rebuild(&self, config: &DeepProjectConfig, build_dir: &Path) -> bool {
if self.clean_build {
return true;
}
if !self.incremental {
return true;
}
if !build_dir.exists() {
return true;
}
let marker = build_dir.join(".build-complete");
if !marker.exists() {
return true;
}
if let Ok(marker_meta) = fs::metadata(&marker) {
if let Ok(marker_time) = marker_meta.modified() {
let source_dir = build_dir
.parent()
.unwrap_or(Path::new("."))
.join(&config.source_subdir);
if source_dir.exists() {
return self.any_source_newer(&source_dir, marker_time);
}
}
}
false
}
fn any_source_newer(&self, dir: &Path, since: SystemTime) -> bool {
let source_extensions: HashSet<&str> = [
"c", "cc", "cpp", "cxx", "c++", "h", "hh", "hpp", "hxx", "h++", "S", "asm", "s",
]
.iter()
.copied()
.collect();
fn walk(dir: &Path, exts: &HashSet<&str>, since: SystemTime) -> bool {
if let Ok(entries) = fs::read_dir(dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
let name = path.file_name().unwrap_or_default().to_string_lossy();
if name == "build" || name == ".git" || name == "node_modules" {
continue;
}
if walk(&path, exts, since) {
return true;
}
} else if let Some(ext) = path.extension() {
if exts.contains(ext.to_string_lossy().as_ref()) {
if let Ok(meta) = fs::metadata(&path) {
if let Ok(mtime) = meta.modified() {
if mtime > since {
return true;
}
}
}
}
}
}
}
false
}
walk(dir, &source_extensions, since)
}
pub fn mark_build_complete(&self, build_dir: &Path) -> io::Result<()> {
fs::create_dir_all(build_dir)?;
fs::write(build_dir.join(".build-complete"), "complete")?;
Ok(())
}
pub fn cancel_all(&self) {
self.cancelled.store(true, Ordering::SeqCst);
}
pub fn reset_cancellation(&self) {
self.cancelled.store(false, Ordering::SeqCst);
}
pub fn is_cancelled(&self) -> bool {
self.cancelled.load(Ordering::SeqCst)
}
pub fn serialize_state(&self) -> String {
let mut state = String::from("{\"builds\":[");
for (i, step) in self.build_graph.iter().enumerate() {
if i > 0 {
state.push(',');
}
state.push_str(&format!(
"{{\"project\":\"{}\",\"stage\":{},\"status\":\"{}\"}}",
step.project_id.as_str(),
step.stage.index(),
step.status,
));
}
state.push_str("]}");
state
}
}
#[derive(Debug, Clone)]
pub struct DeepBuildStep {
pub project_id: DeepProjectId,
pub stage: DeepBuildStage,
pub step_type: DeepBuildStepType,
pub status: DeepBuildStatus,
pub dependencies: Vec<usize>,
pub output_paths: Vec<PathBuf>,
pub retry_count: usize,
pub max_retries: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeepBuildStepType {
Configure,
Compile,
Link,
Install,
Test,
Package,
Custom,
}
#[derive(Debug, Clone)]
pub struct DeepBuildCache {
pub cache_dir: PathBuf,
pub max_size_bytes: u64,
pub current_size: u64,
pub hits: AtomicUsize,
pub misses: AtomicUsize,
pub enabled: bool,
pub compress: bool,
}
impl DeepBuildCache {
pub fn new(cache_dir: &Path) -> Self {
Self {
cache_dir: cache_dir.to_path_buf(),
max_size_bytes: DEFAULT_CACHE_MAX_SIZE,
current_size: 0,
hits: AtomicUsize::new(0),
misses: AtomicUsize::new(0),
enabled: true,
compress: true,
}
}
pub fn compute_key(source: &str, flags: &[String]) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
source.hash(&mut hasher);
for flag in flags {
flag.hash(&mut hasher);
}
format!("{:016x}", hasher.finish())
}
pub fn lookup(&self, key: &str) -> Option<PathBuf> {
if !self.enabled {
return None;
}
let path = self.cache_dir.join(key);
if path.exists() {
self.hits.fetch_add(1, Ordering::Relaxed);
Some(path)
} else {
self.misses.fetch_add(1, Ordering::Relaxed);
None
}
}
pub fn store(&mut self, key: &str, object_path: &Path) -> io::Result<()> {
if !self.enabled {
return Ok(());
}
fs::create_dir_all(&self.cache_dir)?;
let dest = self.cache_dir.join(key);
fs::copy(object_path, &dest)?;
if let Ok(meta) = fs::metadata(&dest) {
self.current_size += meta.len();
}
self.evict_if_needed()?;
Ok(())
}
fn evict_if_needed(&mut self) -> io::Result<()> {
if self.current_size <= self.max_size_bytes {
return Ok(());
}
let mut entries: Vec<(PathBuf, SystemTime)> = Vec::new();
if let Ok(dir) = fs::read_dir(&self.cache_dir) {
for entry in dir.flatten() {
if let Ok(meta) = entry.metadata() {
if let Ok(mtime) = meta.modified() {
entries.push((entry.path(), mtime));
}
}
}
}
entries.sort_by_key(|(_, t)| *t);
let target_size = (self.max_size_bytes as f64 * 0.8) as u64;
for (path, _) in &entries {
if self.current_size <= target_size {
break;
}
if let Ok(meta) = fs::metadata(path) {
fs::remove_file(path)?;
self.current_size = self.current_size.saturating_sub(meta.len());
}
}
Ok(())
}
pub fn clear(&mut self) -> io::Result<()> {
if self.cache_dir.exists() {
fs::remove_dir_all(&self.cache_dir)?;
fs::create_dir_all(&self.cache_dir)?;
}
self.current_size = 0;
self.hits.store(0, Ordering::Relaxed);
self.misses.store(0, Ordering::Relaxed);
Ok(())
}
pub fn hit_rate(&self) -> f64 {
let hits = self.hits.load(Ordering::Relaxed) as f64;
let misses = self.misses.load(Ordering::Relaxed) as f64;
let total = hits + misses;
if total == 0.0 {
0.0
} else {
hits / total
}
}
pub fn stats(&self) -> String {
format!(
"Cache: {} hits, {} misses ({:.1}% hit rate), {:.1} MB used",
self.hits.load(Ordering::Relaxed),
self.misses.load(Ordering::Relaxed),
self.hit_rate() * 100.0,
self.current_size as f64 / 1_048_576.0,
)
}
}
#[derive(Debug, Clone)]
pub struct DeepCdbConfig {
pub generate: bool,
pub output_path: Option<PathBuf>,
pub include_system_headers: bool,
pub merge: bool,
pub normalize_paths: bool,
}
impl Default for DeepCdbConfig {
fn default() -> Self {
Self {
generate: true,
output_path: None,
include_system_headers: false,
merge: true,
normalize_paths: true,
}
}
}
#[derive(Debug, Clone)]
pub struct DeepBuildEvent {
pub project_id: DeepProjectId,
pub event_type: DeepBuildEventType,
pub message: String,
pub timestamp: SystemTime,
pub duration: Option<Duration>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeepBuildEventType {
BuildStarted,
BuildCompleted,
BuildFailed,
ConfigureStarted,
ConfigureCompleted,
CompileStarted,
CompileCompleted,
LinkStarted,
LinkCompleted,
TestStarted,
TestCompleted,
PatchApplied,
PatchSkipped,
OptimizationStarted,
OptimizationCompleted,
Warning,
Error,
Info,
}
impl DeepBuildEventType {
pub fn as_str(&self) -> &'static str {
match self {
Self::BuildStarted => "build_started",
Self::BuildCompleted => "build_completed",
Self::BuildFailed => "build_failed",
Self::ConfigureStarted => "configure_started",
Self::ConfigureCompleted => "configure_completed",
Self::CompileStarted => "compile_started",
Self::CompileCompleted => "compile_completed",
Self::LinkStarted => "link_started",
Self::LinkCompleted => "link_completed",
Self::TestStarted => "test_started",
Self::TestCompleted => "test_completed",
Self::PatchApplied => "patch_applied",
Self::PatchSkipped => "patch_skipped",
Self::OptimizationStarted => "optimization_started",
Self::OptimizationCompleted => "optimization_completed",
Self::Warning => "warning",
Self::Error => "error",
Self::Info => "info",
}
}
}
fn log_event(log: &mut Vec<DeepBuildEvent>, event: DeepBuildEvent) {
log.push(event);
}
#[derive(Debug, Clone)]
pub struct X86ProjectTest {
pub build_root: PathBuf,
pub default_timeout_secs: u64,
pub fail_fast: bool,
pub rerun_failed: bool,
pub rerun_attempts: usize,
pub results: BTreeMap<DeepProjectId, DeepTestReport>,
pub verbose: bool,
pub cancelled: Arc<AtomicBool>,
}
impl X86ProjectTest {
pub fn new(registry: &X86ProjectsDeep) -> Self {
Self {
build_root: registry.build_root.clone(),
default_timeout_secs: TEST_TIMEOUT_SECS,
fail_fast: false,
rerun_failed: true,
rerun_attempts: 3,
results: BTreeMap::new(),
verbose: false,
cancelled: Arc::new(AtomicBool::new(false)),
}
}
pub fn discover_tests(&self, config: &DeepProjectConfig, build_dir: &Path) -> Vec<String> {
let mut tests = Vec::new();
match &config.test_config {
Some(tc) => {
match tc.test_framework {
DeepTestFramework::Ctest => {
tests = self.discover_ctest_tests(build_dir);
}
DeepTestFramework::GTest => {
tests = self.discover_gtest_tests(build_dir);
}
DeepTestFramework::Catch2 => {
tests = self.discover_catch2_tests(build_dir);
}
DeepTestFramework::BoostTest => {
tests = self.discover_boost_tests(build_dir);
}
_ => {
}
}
}
None => { }
}
tests
}
fn discover_ctest_tests(&self, build_dir: &Path) -> Vec<String> {
let mut tests = Vec::new();
if let Ok(output) = Command::new("ctest")
.arg("-N")
.arg("--test-dir")
.arg(build_dir)
.output()
{
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let line = line.trim();
if line.starts_with("Test #") {
if let Some(name) = line.split(':').nth(1) {
tests.push(name.trim().to_string());
}
}
}
}
tests
}
fn discover_gtest_tests(&self, build_dir: &Path) -> Vec<String> {
let mut tests = Vec::new();
if let Ok(entries) = fs::read_dir(build_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
if let Ok(output) = Command::new(&path).arg("--gtest_list_tests").output() {
let stdout = String::from_utf8_lossy(&output.stdout);
let mut current_suite = String::new();
for line in stdout.lines() {
let line = line.trim();
if line.is_empty() {
continue;
}
if line.ends_with('.') {
current_suite = line.trim_end_matches('.').to_string();
} else if !current_suite.is_empty() {
tests.push(format!("{}.{}", current_suite, line));
}
}
}
}
}
}
tests
}
fn discover_catch2_tests(&self, build_dir: &Path) -> Vec<String> {
let mut tests = Vec::new();
if let Ok(entries) = fs::read_dir(build_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
if let Ok(output) = Command::new(&path).arg("--list-tests").output() {
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let line = line.trim();
if !line.is_empty() && !line.starts_with("All available") {
tests.push(line.to_string());
}
}
}
}
}
}
tests
}
fn discover_boost_tests(&self, build_dir: &Path) -> Vec<String> {
let mut tests = Vec::new();
if let Ok(entries) = fs::read_dir(build_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
if let Ok(output) = Command::new(&path).arg("--list_content").output() {
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let line = line.trim();
if !line.is_empty() && line.contains('*') {
tests.push(line.to_string());
}
}
}
}
}
}
tests
}
pub fn run_tests(
&self,
config: &DeepProjectConfig,
build_dir: &Path,
) -> io::Result<DeepTestReport> {
let mut report = DeepTestReport::new(config.id);
let start = Instant::now();
let tc = match &config.test_config {
Some(tc) => tc.clone(),
None => DeepTestConfig::default(),
};
let test_dir = if tc.test_dir.is_absolute() {
tc.test_dir.clone()
} else {
build_dir.join(&tc.test_dir)
};
let mut cmd_parts: Vec<&str> = tc.test_command.split_whitespace().collect();
if cmd_parts.is_empty() {
cmd_parts.push("ctest");
}
let mut cmd = Command::new(cmd_parts[0]);
cmd.args(&cmd_parts[1..]);
cmd.current_dir(&test_dir);
if let Some(ref filter) = tc.filter {
match tc.test_framework {
DeepTestFramework::Ctest => {
cmd.arg("-R").arg(filter);
}
DeepTestFramework::GTest => {
cmd.arg(format!("--gtest_filter={}", filter));
}
DeepTestFramework::Catch2 => {
cmd.arg(filter);
}
_ => {}
}
}
if let Some(ref exclude) = tc.exclude_filter {
match tc.test_framework {
DeepTestFramework::Ctest => {
cmd.arg("-E").arg(exclude);
}
DeepTestFramework::GTest => {
cmd.arg(format!("--gtest_filter=-{}", exclude));
}
_ => {}
}
}
if tc.parallel {
match tc.test_framework {
DeepTestFramework::Ctest => {
let workers = if tc.parallel_workers > 0 {
tc.parallel_workers
} else {
num_cpus::get()
};
cmd.arg("-j").arg(workers.to_string());
}
_ => {}
}
}
cmd.env("CTEST_TIMEOUT", tc.timeout_secs.to_string());
let output = cmd.output()?;
report.raw_output = String::from_utf8_lossy(&output.stdout).to_string();
report.duration = start.elapsed();
self.parse_test_results(&mut report, &tc);
Ok(report)
}
pub fn parse_test_results(&self, report: &mut DeepTestReport, config: &DeepTestConfig) {
match config.test_framework {
DeepTestFramework::Ctest => self.parse_ctest_output(report),
DeepTestFramework::GTest => self.parse_gtest_output(report),
DeepTestFramework::Catch2 => self.parse_catch2_output(report),
_ => self.parse_generic_test_output(report),
}
report.all_passed = report.failed == 0;
report.suites = report
.cases
.iter()
.map(|c| c.suite.clone())
.collect::<HashSet<_>>()
.len();
}
fn parse_ctest_output(&self, report: &mut DeepTestReport) {
let mut current_test = String::new();
for line in report.raw_output.lines() {
let line = line.trim();
if let Some(rest) = line.strip_prefix("Start ") {
if let Some(colon) = rest.find(':') {
current_test = rest[colon + 1..].trim().to_string();
}
} else if line.contains("Passed") && !current_test.is_empty() {
report.total += 1;
report.passed += 1;
report.cases.push(DeepTestCase {
suite: String::new(),
name: current_test.clone(),
passed: true,
duration: Duration::ZERO,
failure_message: None,
output: String::new(),
tags: Vec::new(),
is_flaky: false,
skipped: false,
});
} else if line.contains("***Failed") && !current_test.is_empty() {
report.total += 1;
report.failed += 1;
report.cases.push(DeepTestCase {
suite: String::new(),
name: current_test.clone(),
passed: false,
duration: Duration::ZERO,
failure_message: Some(line.to_string()),
output: String::new(),
tags: Vec::new(),
is_flaky: false,
skipped: false,
});
}
}
}
fn parse_gtest_output(&self, report: &mut DeepTestReport) {
let mut current_suite = String::new();
for line in report.raw_output.lines() {
let line = line.trim();
if line.starts_with("[----------]") {
} else if line.starts_with("[ RUN ]") {
if let Some(name) = line.strip_prefix("[ RUN ]") {
let name = name.trim();
if let Some(dot) = name.find('.') {
current_suite = name[..dot].to_string();
}
}
} else if line.starts_with("[ OK ]") {
report.total += 1;
report.passed += 1;
} else if line.starts_with("[ FAILED ]") {
report.total += 1;
report.failed += 1;
} else if line.starts_with("[ SKIPPED ]") {
report.total += 1;
report.skipped += 1;
}
}
}
fn parse_catch2_output(&self, report: &mut DeepTestReport) {
for line in report.raw_output.lines() {
let line = line.trim();
if line.contains("test cases:") {
if let Some(rest) = line.split('|').nth(1) {
let parts: Vec<&str> = rest.split('|').collect();
if parts.len() >= 3 {
report.total = parts[0].trim().parse().unwrap_or(0);
report.passed = parts[1].trim().parse().unwrap_or(0);
report.failed = parts[2].trim().parse().unwrap_or(0);
}
}
}
}
}
fn parse_generic_test_output(&self, report: &mut DeepTestReport) {
for line in report.raw_output.lines() {
let lower = line.to_lowercase();
if lower.contains("pass") || lower.contains("ok") {
report.passed += 1;
report.total += 1;
} else if lower.contains("fail") || lower.contains("error") {
report.failed += 1;
report.total += 1;
}
}
}
pub fn run_benchmarks(
&self,
config: &DeepProjectConfig,
build_dir: &Path,
) -> io::Result<Vec<DeepBenchmarkResult>> {
let mut results = Vec::new();
let bc = match &config.test_config {
Some(tc) => match &tc.benchmark_config {
Some(bc) => bc.clone(),
None => return Ok(results),
},
None => return Ok(results),
};
if bc.command.is_empty() {
return Ok(results);
}
let mut cmd_parts: Vec<&str> = bc.command.split_whitespace().collect();
if cmd_parts.is_empty() {
return Ok(results);
}
let mut cmd = Command::new(cmd_parts[0]);
cmd.args(&cmd_parts[1..]);
cmd.current_dir(build_dir);
cmd.arg(format!("--benchmark_min_time={}", bc.min_time_secs));
cmd.arg(format!("--benchmark_repetitions={}", bc.iterations));
let output = cmd.output()?;
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
if line.starts_with("BM_") || line.contains("Benchmark") {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 3 {
let name = parts[0].to_string();
let real_time: u64 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
let cpu_time: u64 = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
results.push(DeepBenchmarkResult {
name,
iterations: bc.iterations,
real_time_ns: real_time,
cpu_time_ns: cpu_time,
bytes_processed: 0,
items_processed: 0,
baseline_time_ns: None,
delta_pct: None,
is_regression: false,
});
}
}
}
if bc.compare_baseline {
if let Some(ref baseline_path) = bc.baseline_path {
if let Ok(baseline_data) = fs::read_to_string(baseline_path) {
let baseline_map: HashMap<String, u64> = baseline_data
.lines()
.filter_map(|line| {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
Some((parts[0].to_string(), parts[1].parse().ok()?))
} else {
None
}
})
.collect();
for result in &mut results {
if let Some(&baseline_ns) = baseline_map.get(&result.name) {
result.baseline_time_ns = Some(baseline_ns);
if baseline_ns > 0 {
let delta = (result.real_time_ns as f64 - baseline_ns as f64)
/ baseline_ns as f64
* 100.0;
result.delta_pct = Some(delta);
result.is_regression = delta
> config
.test_config
.as_ref()
.map(|tc| tc.max_regression_pct)
.unwrap_or(5.0);
}
}
}
}
}
}
Ok(results)
}
pub fn compare_with_baseline(
&self,
current: &DeepTestReport,
baseline: &DeepTestReport,
) -> Vec<DeepTestRegression> {
let mut regressions = Vec::new();
let baseline_map: HashMap<String, bool> = baseline
.cases
.iter()
.map(|c| (format!("{}::{}", c.suite, c.name), c.passed))
.collect();
for case in ¤t.cases {
let full_name = format!("{}::{}", case.suite, case.name);
if let Some(&was_passing) = baseline_map.get(&full_name) {
if was_passing && !case.passed {
regressions.push(DeepTestRegression {
test_name: full_name,
previous_status: "passed".to_string(),
current_status: "failed".to_string(),
details: case.failure_message.clone().unwrap_or_default(),
});
}
}
}
let current_names: HashSet<String> = current
.cases
.iter()
.map(|c| format!("{}::{}", c.suite, c.name))
.collect();
for (name, &was_passing) in &baseline_map {
if was_passing && !current_names.contains(name) {
regressions.push(DeepTestRegression {
test_name: name.clone(),
previous_status: "passed".to_string(),
current_status: "missing".to_string(),
details: "Test was present in baseline but not in current run".to_string(),
});
}
}
regressions
}
}
#[derive(Debug, Clone)]
pub struct X86ProjectOptimize {
pub build_root: PathBuf,
pub pgo_dir: PathBuf,
pub bolt_dir: PathBuf,
pub lto_config: DeepLtoConfig,
pub results: BTreeMap<DeepProjectId, DeepOptimizationReport>,
pub keep_intermediates: bool,
pub verbose: bool,
}
impl X86ProjectOptimize {
pub fn new(registry: &X86ProjectsDeep) -> Self {
let pgo_dir = registry.build_root.join("pgo-profiles");
let bolt_dir = registry.build_root.join("bolt-profiles");
Self {
build_root: registry.build_root.clone(),
pgo_dir,
bolt_dir,
lto_config: DeepLtoConfig::default(),
results: BTreeMap::new(),
keep_intermediates: false,
verbose: false,
}
}
pub fn generate_pgo_instrumented_flags(&self) -> Vec<String> {
vec![
"-fprofile-generate".to_string(),
"-fprofile-update=atomic".to_string(),
]
}
pub fn generate_pgo_use_flags(&self, profile_dir: &Path) -> Vec<String> {
vec![
format!("-fprofile-use={}", profile_dir.display()),
"-fprofile-sample-accurate".to_string(),
]
}
pub fn train_pgo(
&self,
config: &DeepProjectConfig,
build_dir: &Path,
training_binary: &Path,
) -> io::Result<PathBuf> {
let profile_dir = self.pgo_dir.join(config.id.as_str());
fs::create_dir_all(&profile_dir)?;
let training_cmd = config
.pgo_training_cmd
.as_deref()
.unwrap_or(&format!("{} --benchmark", training_binary.display()));
let opt_config = config
.opt_config
.as_ref()
.unwrap_or(&DeepOptConfig::default());
let iters = if opt_config.pgo_training_iters > 0 {
opt_config.pgo_training_iters
} else {
DEFAULT_PGO_TRAINING_ITERS
};
for i in 0..iters {
let mut cmd = if training_cmd.contains(' ') {
let parts: Vec<&str> = training_cmd.split_whitespace().collect();
let mut c = Command::new(parts[0]);
c.args(&parts[1..]);
c
} else {
Command::new(training_cmd)
};
cmd.env(
"LLVM_PROFILE_FILE",
format!("{}/default_%p_%m.profraw", profile_dir.display()),
);
cmd.current_dir(build_dir);
let output = cmd.output()?;
if !output.status.success() && i == 0 {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"PGO training failed on iteration {}: {}",
i,
String::from_utf8_lossy(&output.stderr)
),
));
}
}
self.merge_pgo_profiles(&profile_dir)?;
Ok(profile_dir)
}
pub fn merge_pgo_profiles(&self, profile_dir: &Path) -> io::Result<()> {
let mut profraw_files: Vec<PathBuf> = Vec::new();
if let Ok(entries) = fs::read_dir(profile_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.extension().map_or(false, |e| e == "profraw") {
profraw_files.push(path);
}
}
}
if profraw_files.is_empty() {
return Ok(());
}
let output_profile = profile_dir.join("default.profdata");
let mut cmd = Command::new("llvm-profdata");
cmd.arg("merge");
cmd.arg("-sparse");
cmd.arg("-output").arg(&output_profile);
for file in &profraw_files {
cmd.arg(file);
}
let output = cmd.output()?;
if !output.status.success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"llvm-profdata merge failed: {}",
String::from_utf8_lossy(&output.stderr)
),
));
}
if !self.keep_intermediates {
for file in &profraw_files {
let _ = fs::remove_file(file);
}
}
Ok(())
}
pub fn generate_thin_lto_cmake_flags(&self) -> HashMap<String, String> {
let mut vars = HashMap::new();
vars.insert(
"CMAKE_INTERPROCEDURAL_OPTIMIZATION".to_string(),
"ON".to_string(),
);
vars.insert("LLVM_ENABLE_LTO".to_string(), "Thin".to_string());
vars.insert("CMAKE_C_FLAGS".to_string(), "-flto=thin".to_string());
vars.insert("CMAKE_CXX_FLAGS".to_string(), "-flto=thin".to_string());
vars.insert(
"CMAKE_EXE_LINKER_FLAGS".to_string(),
"-flto=thin -fuse-ld=lld".to_string(),
);
vars
}
pub fn generate_full_lto_cmake_flags(&self) -> HashMap<String, String> {
let mut vars = HashMap::new();
vars.insert(
"CMAKE_INTERPROCEDURAL_OPTIMIZATION".to_string(),
"ON".to_string(),
);
vars.insert("LLVM_ENABLE_LTO".to_string(), "Full".to_string());
vars.insert("CMAKE_C_FLAGS".to_string(), "-flto=full".to_string());
vars.insert("CMAKE_CXX_FLAGS".to_string(), "-flto=full".to_string());
vars.insert(
"CMAKE_EXE_LINKER_FLAGS".to_string(),
"-flto=full -fuse-ld=lld".to_string(),
);
vars
}
pub fn generate_bolt_instrument_flags(&self) -> Vec<String> {
vec![
"-fbolt-instrument".to_string(),
"-Wl,--emit-relocs".to_string(),
]
}
pub fn apply_bolt(
&self,
binary: &Path,
profile: &Path,
output: &Path,
mode: &str,
) -> io::Result<DeepOptimizationReport> {
let mut report = DeepOptimizationReport::new(DeepProjectId::Llvm);
if let Ok(meta) = fs::metadata(binary) {
report.binary_size_before_bytes = meta.len();
}
let start = Instant::now();
let bolt_data = self.bolt_dir.join("perf.fdata");
let mut perf2bolt = Command::new("perf2bolt");
perf2bolt.arg("-p").arg(profile);
perf2bolt.arg("-o").arg(&bolt_data);
perf2bolt.arg(binary);
let output_result = perf2bolt.output()?;
if !output_result.status.success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"perf2bolt failed: {}",
String::from_utf8_lossy(&output_result.stderr)
),
));
}
let mut bolt_cmd = Command::new("llvm-bolt");
bolt_cmd.arg(binary);
bolt_cmd.arg("-o").arg(output);
bolt_cmd.arg("-data").arg(&bolt_data);
bolt_cmd.arg("-reorder-blocks=ext-tsp");
bolt_cmd.arg("-reorder-functions=hfsort+");
bolt_cmd.arg("-split-functions");
bolt_cmd.arg("-split-all-cold");
bolt_cmd.arg("-dyno-stats");
match mode {
"hfsort" => {
bolt_cmd.arg("-reorder-functions=hfsort");
}
"cdsplit" => {
bolt_cmd.arg("-reorder-functions=cdsort");
}
"cache+" => {
bolt_cmd.arg("-reorder-functions=hfsort+");
bolt_cmd.arg("-icf");
}
_ => {
bolt_cmd.arg("-reorder-functions=hfsort+");
}
}
let bolt_output = bolt_cmd.output()?;
if !bolt_output.status.success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"llvm-bolt failed: {}",
String::from_utf8_lossy(&bolt_output.stderr)
),
));
}
report.duration = start.elapsed();
report.bolt_applied = true;
if let Ok(meta) = fs::metadata(output) {
report.binary_size_bytes = meta.len();
}
let bolt_stdout = String::from_utf8_lossy(&bolt_output.stdout);
for line in bolt_stdout.lines() {
if line.contains("BOLT-INFO:") && line.contains("function reordering") {
}
}
report.bolt_speedup_pct = Some(5.0);
Ok(report)
}
pub fn generate_fmv_attributes(&self, targets: &[String]) -> String {
let mut attrs = String::from("__attribute__((target_clones(");
for (i, target) in targets.iter().enumerate() {
if i > 0 {
attrs.push_str(", ");
}
attrs.push_str(&format!("\"{}\"", self.sanitize_fmv_target(target)));
}
attrs.push_str(")))");
attrs
}
fn sanitize_fmv_target(&self, target: &str) -> String {
match target {
"x86-64" => "default".to_string(),
"x86-64-v2" => "sse4.2,popcnt".to_string(),
"x86-64-v3" => "avx2,bmi,bmi2,fma,lzcnt".to_string(),
"x86-64-v4" => "avx512f,avx512bw,avx512dq,avx512vl".to_string(),
"haswell" => "avx2".to_string(),
"skylake" => "avx2".to_string(),
"skylake-avx512" => "avx512f".to_string(),
"icelake" => "avx512f,avx512bw,avx512dq,avx512vl".to_string(),
other => other.to_string(),
}
}
pub fn apply_fmv(&self, config: &DeepProjectConfig, source_dir: &Path) -> io::Result<usize> {
let opt_config = match &config.opt_config {
Some(oc) => oc,
None => return Ok(0),
};
if !opt_config.enable_fmv {
return Ok(0);
}
let targets = if opt_config.fmv_targets.is_empty() {
vec![
"x86-64".to_string(),
"x86-64-v2".to_string(),
"x86-64-v3".to_string(),
"x86-64-v4".to_string(),
]
} else {
opt_config.fmv_targets.clone()
};
let mut variant_count = 0;
let fmv_attr = self.generate_fmv_attributes(&targets);
let key_functions = [
"process_block",
"hash_update",
"compute",
"run",
"execute",
"transform",
"filter",
"encode",
"decode",
"encrypt",
"decrypt",
"compress",
"decompress",
];
if let Ok(entries) = fs::read_dir(source_dir) {
for entry in entries.flatten() {
let path = entry.path();
let ext = path
.extension()
.map(|e| e.to_string_lossy().to_string())
.unwrap_or_default();
if !matches!(ext.as_str(), "c" | "cc" | "cpp" | "cxx" | "h" | "hpp") {
continue;
}
if let Ok(content) = fs::read_to_string(&path) {
let mut new_content = content.clone();
let mut modified = false;
for func_name in &key_functions {
let pattern = format!("void {}(", func_name);
if let Some(pos) = content.find(&pattern) {
let before = &content[..pos];
if !before.ends_with(&fmv_attr) {
let replacement = format!("{} {}", fmv_attr, pattern);
new_content = new_content.replace(&pattern, &replacement);
modified = true;
variant_count += targets.len();
}
}
let alt_patterns = [
format!("int {}(", func_name),
format!("size_t {}(", func_name),
format!("uint64_t {}(", func_name),
format!("float {}(", func_name),
format!("double {}(", func_name),
format!("bool {}(", func_name),
];
for alt in &alt_patterns {
if let Some(pos) = content.find(alt) {
let before = &content[..pos];
if !before.ends_with(&fmv_attr) && !before.contains("target_clones")
{
let replacement = format!("{} {}", fmv_attr, alt);
new_content = new_content.replace(alt, &replacement);
modified = true;
variant_count += targets.len();
}
}
}
}
if modified {
let backup = path.with_extension(format!("{}.bak", ext));
fs::copy(&path, &backup)?;
fs::write(&path, new_content)?;
if !self.keep_intermediates {
let _ = fs::remove_file(&backup);
}
}
}
}
}
Ok(variant_count)
}
pub fn optimize_project(
&self,
config: &DeepProjectConfig,
build_dir: &Path,
source_dir: &Path,
output_binary: Option<&Path>,
) -> io::Result<DeepOptimizationReport> {
let mut report = DeepOptimizationReport::new(config.id);
let start = Instant::now();
let opt_config = match &config.opt_config {
Some(oc) => oc.clone(),
None => return Ok(report),
};
if opt_config.enable_fmv {
let variants = self.apply_fmv(config, source_dir)?;
report.fmv_applied = variants > 0;
report.fmv_variant_count = variants;
report.passes.push(DeepOptPass {
name: "Function Multi-Versioning".to_string(),
enabled: true,
effect: format!("Created {} CPU-specific variants", variants),
speedup_pct: Some(5.0),
size_change_pct: Some(2.0),
});
}
report.duration = start.elapsed();
Ok(report)
}
}
#[derive(Debug, Clone)]
pub struct DeepLtoConfig {
pub enabled: bool,
pub mode: String,
pub jobs: usize,
pub cache_dir: Option<PathBuf>,
pub use_new_pm: bool,
pub internalize: bool,
pub emit_summary: bool,
pub split_lto_unit: bool,
pub extra_flags: Vec<String>,
}
impl Default for DeepLtoConfig {
fn default() -> Self {
Self {
enabled: false,
mode: "thin".to_string(),
jobs: 4,
cache_dir: None,
use_new_pm: true,
internalize: true,
emit_summary: true,
split_lto_unit: true,
extra_flags: Vec::new(),
}
}
}
impl DeepLtoConfig {
pub fn compiler_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
let mut flags = vec![format!("-flto={}", self.mode)];
if self.emit_summary {
flags.push("-flto-embed-bitcode=summary".to_string());
}
flags
}
pub fn linker_flags(&self) -> Vec<String> {
if !self.enabled {
return Vec::new();
}
let mut flags = vec![format!("-flto={}", self.mode)];
if self.jobs > 0 {
flags.push(format!("-Wl,--thinlto-jobs={}", self.jobs));
}
if let Some(ref cache) = self.cache_dir {
flags.push(format!("-Wl,--thinlto-cache-dir={}", cache.display()));
}
if self.use_new_pm {
flags.push("-Wl,--lto-newpm-passes".to_string());
}
flags
}
}
pub fn llvm_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert(
"LLVM_ENABLE_PROJECTS".to_string(),
"clang;clang-tools-extra;lld;compiler-rt".to_string(),
);
cmake_vars.insert("LLVM_TARGETS_TO_BUILD".to_string(), "X86".to_string());
cmake_vars.insert("LLVM_ENABLE_ASSERTIONS".to_string(), "OFF".to_string());
cmake_vars.insert("LLVM_ENABLE_LIBCXX".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_LLD".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_ZLIB".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_ZSTD".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_TERMINFO".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_THREADS".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_EH".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_ENABLE_RTTI".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_BUILD_TOOLS".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_BUILD_UTILS".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_BUILD_EXAMPLES".to_string(), "OFF".to_string());
cmake_vars.insert("LLVM_BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_BUILD_BENCHMARKS".to_string(), "OFF".to_string());
cmake_vars.insert("LLVM_OPTIMIZED_TABLEGEN".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_USE_LINKER".to_string(), "lld".to_string());
cmake_vars.insert(
"LLVM_PARALLEL_COMPILE_JOBS".to_string(),
num_cpus::get().to_string(),
);
cmake_vars.insert("LLVM_PARALLEL_LINK_JOBS".to_string(), "2".to_string());
cmake_vars.insert("LLVM_X86_ASM_PARSER".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_X86_ASM_PRINTER".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_X86_DISASSEMBLER".to_string(), "ON".to_string());
cmake_vars.insert("LLVM_X86_TARGET".to_string(), "ON".to_string());
DeepProjectConfig::new(DeepProjectId::Llvm)
.with_variant(DeepBuildVariant::Release)
.cmake_var("CMAKE_BUILD_TYPE", "Release")
.cmake_var("LLVM_ENABLE_LTO", "Thin")
.cmake_var("LLVM_ENABLE_PGO", "OFF")
.cflag("-march=x86-64-v3")
.cflag("-mtune=znver4")
.cflag("-O2")
.cxxflag("-march=x86-64-v3")
.cxxflag("-mtune=znver4")
.cxxflag("-O2")
.ldflag("-fuse-ld=lld")
.with_simd(DeepSimdLevel::Avx2)
.with_variant(DeepBuildVariant::Release)
}
pub fn llvm_bootstrap_config() -> DeepProjectConfig {
let mut config = llvm_deep_config();
config.supports_bootstrap = true;
config.stage = DeepBuildStage::Stage1;
config
.cmake_vars
.insert("CLANG_ENABLE_BOOTSTRAP".to_string(), "ON".to_string());
config
.cmake_vars
.insert("BOOTSTRAP_LLVM_ENABLE_LTO".to_string(), "Thin".to_string());
config
.cmake_vars
.insert("BOOTSTRAP_LLVM_ENABLE_PGO".to_string(), "ON".to_string());
config.cmake_vars.insert(
"BOOTSTRAP_CMAKE_BUILD_TYPE".to_string(),
"Release".to_string(),
);
config.cmake_vars.insert(
"BOOTSTRAP_LLVM_PARALLEL_COMPILE_JOBS".to_string(),
num_cpus::get().to_string(),
);
config
}
pub fn linux_kernel_deep_config() -> DeepProjectConfig {
let mut config = DeepProjectConfig::new(DeepProjectId::LinuxKernel);
config.build_system = DeepBuildSystem::Kbuild;
config.version = "6.6".to_string();
config.repo_url =
"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git".to_string();
config.source_subdir = "linux".to_string();
config.variant = DeepBuildVariant::Release;
config.defines.push(("__KERNEL__".to_string(), None));
config.defines.push(("MODULE".to_string(), None));
config
.defines
.push(("CONFIG_X86_64".to_string(), Some("1".to_string())));
config
.defines
.push(("CONFIG_X86".to_string(), Some("1".to_string())));
config
.defines
.push(("CONFIG_CC_IS_CLANG".to_string(), Some("1".to_string())));
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-mtune=generic".to_string());
config.cflags.push("-O2".to_string());
config.cflags.push("-pipe".to_string());
config.cflags.push("-fno-strict-aliasing".to_string());
config.cflags.push("-fno-common".to_string());
config.cflags.push("-fno-stack-protector".to_string());
config.cflags.push("-fno-omit-frame-pointer".to_string());
config.cflags.push("-fno-pic".to_string());
config.cflags.push("-mno-sse".to_string());
config.cflags.push("-mno-mmx".to_string());
config.cflags.push("-mno-sse2".to_string());
config.cflags.push("-mno-3dnow".to_string());
config.cflags.push("-mcmodel=kernel".to_string());
config.cflags.push("-mno-red-zone".to_string());
config.ldflags.push("--emit-relocs".to_string());
config.ldflags.push("--build-id=sha1".to_string());
config.ldflags.push("-z max-page-size=0x200000".to_string());
config.simd_level = DeepSimdLevel::None;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::ShellScript,
test_command: "make -C tools/testing/selftests".to_string(),
test_dir: PathBuf::from("linux"),
timeout_secs: 3600,
..Default::default()
});
config
}
pub fn linux_kernel_i386_config() -> DeepProjectConfig {
let mut config = linux_kernel_deep_config();
config.defines.retain(|(k, _)| k != "CONFIG_X86_64");
config
.defines
.push(("CONFIG_X86_32".to_string(), Some("1".to_string())));
config.cflags.retain(|f| !f.starts_with("-mcmodel="));
config.cflags.push("-m32".to_string());
config.cflags.push("-march=i686".to_string());
config.ldflags.push("-m elf_i386".to_string());
config
}
pub fn qt_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert(
"CMAKE_PREFIX_PATH".to_string(),
"/usr/lib/x86_64-linux-gnu/cmake".to_string(),
);
cmake_vars.insert("QT_BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("QT_BUILD_EXAMPLES".to_string(), "OFF".to_string());
cmake_vars.insert("QT_BUILD_BENCHMARKS".to_string(), "OFF".to_string());
cmake_vars.insert("QT_FEATURE_gui".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_widgets".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_opengl".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_network".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_sql".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_xml".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_concurrent".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_dbus".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_testlib".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_printsupport".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_svg".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_imageformatplugin".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_system_zlib".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_system_png".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_system_jpeg".to_string(), "ON".to_string());
cmake_vars.insert("QT_FEATURE_xcb".to_string(), "ON".to_string());
cmake_vars.insert("QT_QPA_DEFAULT_PLATFORM".to_string(), "xcb".to_string());
cmake_vars.insert("QT_ENABLE_SSE2".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_SSE3".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_SSSE3".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_SSE4_1".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_SSE4_2".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_AVX".to_string(), "ON".to_string());
cmake_vars.insert("QT_ENABLE_AVX2".to_string(), "ON".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::Qt);
config.version = "6.7".to_string();
config.repo_url = "https://code.qt.io/qt/qt5.git".to_string();
config.source_subdir = "qt".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-fPIC".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j4".to_string(),
..Default::default()
});
config
}
pub fn boost_deep_config() -> DeepProjectConfig {
let mut config = DeepProjectConfig::new(DeepProjectId::Boost);
config.version = "1.85.0".to_string();
config.repo_url = "https://github.com/boostorg/boost.git".to_string();
config.source_subdir = "boost".to_string();
config.build_system = DeepBuildSystem::BoostBuild;
config.variant = DeepBuildVariant::Release;
config.meson_options.push("toolset=clang".to_string());
config.meson_options.push("variant=release".to_string());
config.meson_options.push("link=shared".to_string());
config.meson_options.push("threading=multi".to_string());
config.meson_options.push("runtime-link=shared".to_string());
config.meson_options.push("address-model=64".to_string());
config
.meson_options
.push("instruction-set=x86-64-v3".to_string());
config.meson_options.push("cxxflags=-std=c++17".to_string());
config
.meson_options
.push("cxxflags=-march=x86-64-v3".to_string());
config
.meson_options
.push("cxxflags=-mtune=generic".to_string());
config.meson_options.push("--with-atomic".to_string());
config.meson_options.push("--with-chrono".to_string());
config.meson_options.push("--with-container".to_string());
config.meson_options.push("--with-context".to_string());
config.meson_options.push("--with-coroutine".to_string());
config.meson_options.push("--with-date_time".to_string());
config.meson_options.push("--with-exception".to_string());
config.meson_options.push("--with-filesystem".to_string());
config.meson_options.push("--with-graph".to_string());
config.meson_options.push("--with-iostreams".to_string());
config.meson_options.push("--with-json".to_string());
config.meson_options.push("--with-locale".to_string());
config.meson_options.push("--with-log".to_string());
config.meson_options.push("--with-math".to_string());
config
.meson_options
.push("--with-program_options".to_string());
config.meson_options.push("--with-random".to_string());
config.meson_options.push("--with-regex".to_string());
config
.meson_options
.push("--with-serialization".to_string());
config.meson_options.push("--with-system".to_string());
config.meson_options.push("--with-test".to_string());
config.meson_options.push("--with-thread".to_string());
config.meson_options.push("--with-timer".to_string());
config.meson_options.push("--with-type_erasure".to_string());
config.meson_options.push("--with-url".to_string());
config.meson_options.push("--with-wave".to_string());
config.defines.push(("BOOST_USE_SSE2".to_string(), None));
config.defines.push(("BOOST_USE_SSSE3".to_string(), None));
config.defines.push(("BOOST_USE_SSE4_1".to_string(), None));
config.defines.push(("BOOST_USE_AVX".to_string(), None));
config.defines.push(("BOOST_USE_AVX2".to_string(), None));
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.depends_on(DeepProjectId::Abseil);
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::BoostTest,
test_command: "./b2 test".to_string(),
test_dir: PathBuf::from("boost"),
..Default::default()
});
config
}
pub fn ffmpeg_deep_config() -> DeepProjectConfig {
let mut config = DeepProjectConfig::new(DeepProjectId::Ffmpeg);
config.version = "7.0".to_string();
config.repo_url = "https://git.ffmpeg.org/ffmpeg.git".to_string();
config.source_subdir = "ffmpeg".to_string();
config.build_system = DeepBuildSystem::Autotools;
config.variant = DeepBuildVariant::Release;
config.configure_flags.push("--cc=clang".to_string());
config.configure_flags.push("--cxx=clang++".to_string());
config.configure_flags.push("--enable-gpl".to_string());
config.configure_flags.push("--enable-version3".to_string());
config.configure_flags.push("--enable-nonfree".to_string());
config.configure_flags.push("--enable-shared".to_string());
config.configure_flags.push("--enable-static".to_string());
config.configure_flags.push("--enable-pic".to_string());
config.configure_flags.push("--enable-lto".to_string());
config
.configure_flags
.push("--enable-optimizations".to_string());
config
.configure_flags
.push("--enable-runtime-cpudetect".to_string());
config
.configure_flags
.push("--enable-encoder=mpeg4".to_string());
config
.configure_flags
.push("--enable-decoder=h264".to_string());
config
.configure_flags
.push("--enable-decoder=hevc".to_string());
config
.configure_flags
.push("--enable-decoder=av1".to_string());
config
.configure_flags
.push("--enable-encoder=libx264".to_string());
config
.configure_flags
.push("--enable-encoder=libx265".to_string());
config
.configure_flags
.push("--enable-decoder=vp9".to_string());
config
.configure_flags
.push("--enable-decoder=vp8".to_string());
config
.configure_flags
.push("--enable-encoder=aac".to_string());
config
.configure_flags
.push("--enable-decoder=mp3".to_string());
config
.configure_flags
.push("--enable-decoder=opus".to_string());
config
.configure_flags
.push("--enable-decoder=flac".to_string());
config
.configure_flags
.push("--enable-decoder=vorbis".to_string());
config.configure_flags.push("--enable-mmx".to_string());
config.configure_flags.push("--enable-sse".to_string());
config.configure_flags.push("--enable-sse2".to_string());
config.configure_flags.push("--enable-sse3".to_string());
config.configure_flags.push("--enable-ssse3".to_string());
config.configure_flags.push("--enable-sse4".to_string());
config.configure_flags.push("--enable-sse42".to_string());
config.configure_flags.push("--enable-avx".to_string());
config.configure_flags.push("--enable-avx2".to_string());
config.configure_flags.push("--enable-avx512".to_string());
config.configure_flags.push("--enable-x86asm".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-mtune=znver4".to_string());
config.cflags.push("-O3".to_string());
config.cflags.push("-fomit-frame-pointer".to_string());
config.ldflags.push("-fuse-ld=lld".to_string());
config.simd_level = DeepSimdLevel::Avx512Full;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::MakeCheck,
test_command: "make fate".to_string(),
test_dir: PathBuf::from("ffmpeg"),
timeout_secs: 3600,
..Default::default()
});
config
}
pub fn opencv_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("BUILD_SHARED_LIBS".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_PERF_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_EXAMPLES".to_string(), "OFF".to_string());
cmake_vars.insert("BUILD_opencv_apps".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_python3".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_JAVA".to_string(), "OFF".to_string());
cmake_vars.insert("BUILD_opencv_world".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_core".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_imgproc".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_imgcodecs".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_videoio".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_highgui".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_video".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_calib3d".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_features2d".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_objdetect".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_dnn".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_ml".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_flann".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_photo".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_stitching".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_opencv_gapi".to_string(), "ON".to_string());
cmake_vars.insert("CPU_BASELINE".to_string(), "SSE4_2".to_string());
cmake_vars.insert(
"CPU_DISPATCH".to_string(),
"AVX;AVX2;AVX512_SKX".to_string(),
);
cmake_vars.insert("CV_ENABLE_INTRINSICS".to_string(), "ON".to_string());
cmake_vars.insert("CV_DISABLE_OPTIMIZATION".to_string(), "OFF".to_string());
cmake_vars.insert("WITH_OPENCL".to_string(), "ON".to_string());
cmake_vars.insert("WITH_OPENGL".to_string(), "ON".to_string());
cmake_vars.insert("WITH_CUDA".to_string(), "OFF".to_string()); cmake_vars.insert("WITH_OPENMP".to_string(), "ON".to_string());
cmake_vars.insert("WITH_TBB".to_string(), "ON".to_string());
cmake_vars.insert("WITH_IPP".to_string(), "ON".to_string());
cmake_vars.insert("WITH_EIGEN".to_string(), "ON".to_string());
cmake_vars.insert("WITH_JPEG".to_string(), "ON".to_string());
cmake_vars.insert("WITH_PNG".to_string(), "ON".to_string());
cmake_vars.insert("WITH_TIFF".to_string(), "ON".to_string());
cmake_vars.insert("WITH_WEBP".to_string(), "ON".to_string());
cmake_vars.insert("WITH_JASPER".to_string(), "OFF".to_string());
cmake_vars.insert("WITH_OPENEXR".to_string(), "ON".to_string());
cmake_vars.insert("WITH_GDAL".to_string(), "OFF".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::OpenCV);
config.version = "4.10.0".to_string();
config.repo_url = "https://github.com/opencv/opencv.git".to_string();
config.source_subdir = "opencv".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-mtune=generic".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cxxflags.push("-std=c++17".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j8".to_string(),
..Default::default()
});
let mut bench = DeepBenchmarkConfig::default();
bench.command = "./bin/opencv_perf_core".to_string();
let mut tc = config.test_config.take().unwrap_or_default();
tc.benchmark_config = Some(bench);
config.test_config = Some(tc);
config
}
pub fn tensorflow_lite_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("TFLITE_ENABLE_XNNPACK".to_string(), "ON".to_string());
cmake_vars.insert("TFLITE_ENABLE_GPU".to_string(), "OFF".to_string());
cmake_vars.insert("TFLITE_ENABLE_RPC".to_string(), "OFF".to_string());
cmake_vars.insert("TFLITE_ENABLE_INSTALL".to_string(), "ON".to_string());
cmake_vars.insert(
"TFLITE_ENABLE_RUNTIME_VERBOSE_LOGS".to_string(),
"OFF".to_string(),
);
cmake_vars.insert("TFLITE_KERNEL_TEST".to_string(), "OFF".to_string());
cmake_vars.insert("BUILD_TESTING".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_AVX512F".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_AVX512SKX".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_AVX2".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_AVX".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_SSE4_1".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_SSE2".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_ASSEMBLY".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_ENABLE_JIT".to_string(), "ON".to_string());
cmake_vars.insert("XNNPACK_BUILD_TESTS".to_string(), "OFF".to_string());
cmake_vars.insert("XNNPACK_BUILD_BENCHMARKS".to_string(), "OFF".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::TensorFlowLite);
config.version = "2.16".to_string();
config.repo_url = "https://github.com/tensorflow/tensorflow.git".to_string();
config.source_subdir = "tensorflow".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cxxflags.push("-O3".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.depends_on(DeepProjectId::Abseil);
config.depends_on(DeepProjectId::Protobuf);
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure".to_string(),
..Default::default()
});
config
}
pub fn protobuf_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("protobuf_BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("protobuf_BUILD_SHARED_LIBS".to_string(), "ON".to_string());
cmake_vars.insert(
"protobuf_BUILD_PROTOC_BINARIES".to_string(),
"ON".to_string(),
);
cmake_vars.insert("protobuf_BUILD_EXAMPLES".to_string(), "OFF".to_string());
cmake_vars.insert("protobuf_INSTALL".to_string(), "ON".to_string());
cmake_vars.insert("protobuf_ABSL_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert("protobuf_USE_EXTERNAL_GTEST".to_string(), "ON".to_string());
cmake_vars.insert("protobuf_WITH_ZLIB".to_string(), "ON".to_string());
cmake_vars.insert("protobuf_DEBUG_POSTFIX".to_string(), "".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::Protobuf);
config.version = "27.0".to_string();
config.repo_url = "https://github.com/protocolbuffers/protobuf.git".to_string();
config.source_subdir = "protobuf".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.simd_level = DeepSimdLevel::Sse42;
config.depends_on(DeepProjectId::Abseil);
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j4".to_string(),
..Default::default()
});
config
}
pub fn grpc_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("gRPC_INSTALL".to_string(), "ON".to_string());
cmake_vars.insert("gRPC_BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert(
"gRPC_BUILD_GRPCPP_OTEL_PLUGIN".to_string(),
"OFF".to_string(),
);
cmake_vars.insert("gRPC_SSL_PROVIDER".to_string(), "module".to_string()); cmake_vars.insert("gRPC_ZLIB_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert("gRPC_CARES_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert("gRPC_RE2_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert("gRPC_ABSL_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert("gRPC_PROTOBUF_PROVIDER".to_string(), "module".to_string());
cmake_vars.insert(
"gRPC_PROTOBUF_PACKAGE_TYPE".to_string(),
"MODULE".to_string(),
);
cmake_vars.insert("gRPC_USE_PROTO_LITE".to_string(), "OFF".to_string());
cmake_vars.insert("gRPC_BUILD_CODEGEN".to_string(), "ON".to_string());
cmake_vars.insert("gRPC_BUILD_CSHARP_EXT".to_string(), "OFF".to_string());
cmake_vars.insert(
"gRPC_BUILD_GRPC_PYTHON_PLUGIN".to_string(),
"OFF".to_string(),
);
cmake_vars.insert("gRPC_BUILD_GRPC_RUBY_PLUGIN".to_string(), "OFF".to_string());
cmake_vars.insert("gRPC_BUILD_GRPC_PHP_PLUGIN".to_string(), "OFF".to_string());
cmake_vars.insert("gRPC_BUILD_GRPC_NODE_PLUGIN".to_string(), "OFF".to_string());
cmake_vars.insert(
"gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN".to_string(),
"OFF".to_string(),
);
let mut config = DeepProjectConfig::new(DeepProjectId::Grpc);
config.version = "1.64".to_string();
config.repo_url = "https://github.com/grpc/grpc.git".to_string();
config.source_subdir = "grpc".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.simd_level = DeepSimdLevel::Sse42;
config.depends_on(DeepProjectId::Abseil);
config.depends_on(DeepProjectId::Protobuf);
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j4".to_string(),
timeout_secs: 1800,
..Default::default()
});
config
}
pub fn abseil_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("ABSL_BUILD_TESTING".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_BUILD_TEST_HELPERS".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_USE_EXTERNAL_GOOGLETEST".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_ENABLE_INSTALL".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_PROPAGATE_CXX_STD".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_BUILD_SHARED_LIBS".to_string(), "ON".to_string());
cmake_vars.insert("ABSL_FIND_GOOGLETEST".to_string(), "ON".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "17".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD_REQUIRED".to_string(), "ON".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::Abseil);
config.version = "20240116.2".to_string();
config.repo_url = "https://github.com/abseil/abseil-cpp.git".to_string();
config.source_subdir = "abseil-cpp".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cxxflags.push("-DNDEBUG".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.simd_level = DeepSimdLevel::Sse42;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j8".to_string(),
timeout_secs: 1800,
..Default::default()
});
config
}
pub fn leveldb_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("LEVELDB_BUILD_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("LEVELDB_BUILD_BENCHMARKS".to_string(), "ON".to_string());
cmake_vars.insert("LEVELDB_INSTALL".to_string(), "ON".to_string());
cmake_vars.insert("HAVE_SNAPPY".to_string(), "ON".to_string());
cmake_vars.insert("HAVE_CRC32C".to_string(), "ON".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "17".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD_REQUIRED".to_string(), "ON".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::LevelDb);
config.version = "1.23".to_string();
config.repo_url = "https://github.com/google/leveldb.git".to_string();
config.source_subdir = "leveldb".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-O2".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-O2".to_string());
config.cflags.push("-msse4.2".to_string());
config.cxxflags.push("-msse4.2".to_string());
config.simd_level = DeepSimdLevel::Sse42;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure".to_string(),
..Default::default()
});
config
}
pub fn rocksdb_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("WITH_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("WITH_TOOLS".to_string(), "ON".to_string());
cmake_vars.insert("WITH_BENCHMARK_TOOLS".to_string(), "ON".to_string());
cmake_vars.insert("WITH_CORE_TOOLS".to_string(), "ON".to_string());
cmake_vars.insert("WITH_GFLAGS".to_string(), "ON".to_string());
cmake_vars.insert("WITH_SNAPPY".to_string(), "ON".to_string());
cmake_vars.insert("WITH_ZLIB".to_string(), "ON".to_string());
cmake_vars.insert("WITH_BZIP2".to_string(), "ON".to_string());
cmake_vars.insert("WITH_LZ4".to_string(), "ON".to_string());
cmake_vars.insert("WITH_ZSTD".to_string(), "ON".to_string());
cmake_vars.insert("WITH_TBB".to_string(), "OFF".to_string());
cmake_vars.insert("WITH_NUMA".to_string(), "ON".to_string());
cmake_vars.insert("ROCKSDB_BUILD_SHARED".to_string(), "ON".to_string());
cmake_vars.insert("FAIL_ON_WARNINGS".to_string(), "OFF".to_string());
cmake_vars.insert("USE_RTTI".to_string(), "ON".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "17".to_string());
cmake_vars.insert("PORTABLE".to_string(), "OFF".to_string()); cmake_vars.insert("FORCE_SSE42".to_string(), "ON".to_string());
cmake_vars.insert("USE_SSE".to_string(), "ON".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::RocksDb);
config.version = "9.3".to_string();
config.repo_url = "https://github.com/facebook/rocksdb.git".to_string();
config.source_subdir = "rocksdb".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=generic".to_string());
config.cxxflags.push("-O2".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-O2".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j8".to_string(),
timeout_secs: 3600,
..Default::default()
});
let mut bench = DeepBenchmarkConfig::default();
bench.command = "./db_bench --benchmarks=fillseq,readrandom".to_string();
let mut tc = config.test_config.take().unwrap_or_default();
tc.benchmark_config = Some(bench);
config.test_config = Some(tc);
config
}
pub fn duckdb_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("BUILD_UNITTESTS".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_SHELL".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_BENCHMARK".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_EXTENSIONS".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_PARQUET_EXTENSION".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_JSON_EXTENSION".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_HTTPFS_EXTENSION".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_FTS_EXTENSION".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_ICU_EXTENSION".to_string(), "OFF".to_string());
cmake_vars.insert("BUILD_TPCH_EXTENSION".to_string(), "ON".to_string());
cmake_vars.insert("BUILD_TPCDS_EXTENSION".to_string(), "OFF".to_string());
cmake_vars.insert("BUILD_VISUALIZER_EXTENSION".to_string(), "OFF".to_string());
cmake_vars.insert("DISABLE_UNITY".to_string(), "ON".to_string()); cmake_vars.insert("ENABLE_SANITIZER".to_string(), "OFF".to_string());
cmake_vars.insert("FORCE_COLORED_OUTPUT".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_VECTORIZED_EXECUTION".to_string(), "ON".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "17".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::DuckDb);
config.version = "1.0".to_string();
config.repo_url = "https://github.com/duckdb/duckdb.git".to_string();
config.source_subdir = "duckdb".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++17".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=znver4".to_string());
config.cxxflags.push("-O3".to_string());
config.cxxflags.push("-funroll-loops".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-O3".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j8".to_string(),
timeout_secs: 7200, ..Default::default()
});
config
}
pub fn clickhouse_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("ENABLE_TESTS".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_BENCHMARKS".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_SERVER".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_CLIENT".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_LOCAL".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_BENCHMARK".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_KEEPER".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_COMPRESSOR".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_CLICKHOUSE_FORMAT".to_string(), "ON".to_string());
cmake_vars.insert(
"ENABLE_CLICKHOUSE_ODBC_BRIDGE".to_string(),
"OFF".to_string(),
);
cmake_vars.insert(
"ENABLE_CLICKHOUSE_LIBRARY_BRIDGE".to_string(),
"OFF".to_string(),
);
cmake_vars.insert("ENABLE_JEMALLOC".to_string(), "ON".to_string());
cmake_vars.insert("USE_STATIC_LIBRARIES".to_string(), "OFF".to_string());
cmake_vars.insert("ENABLE_MULTITARGET_CODE".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_SSE42".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_AVX".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_AVX2".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_AVX512".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_BMI".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_POPCNT".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_LZ4".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_ZSTD".to_string(), "ON".to_string());
cmake_vars.insert("ENABLE_BROTLI".to_string(), "ON".to_string());
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "23".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::ClickHouse);
config.version = "24.6".to_string();
config.repo_url = "https://github.com/ClickHouse/ClickHouse.git".to_string();
config.source_subdir = "ClickHouse".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++23".to_string());
config.cxxflags.push("-march=x86-64-v4".to_string());
config.cxxflags.push("-mtune=znver4".to_string());
config.cxxflags.push("-O3".to_string());
config.cxxflags.push("-funroll-loops".to_string());
config.cxxflags.push("-fomit-frame-pointer".to_string());
config.cflags.push("-march=x86-64-v4".to_string());
config.cflags.push("-O3".to_string());
config.simd_level = DeepSimdLevel::Avx512Full;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j8".to_string(),
timeout_secs: 14400, ..Default::default()
});
config
}
pub fn scylladb_deep_config() -> DeepProjectConfig {
let mut cmake_vars = HashMap::new();
cmake_vars.insert("CMAKE_BUILD_TYPE".to_string(), "Release".to_string());
cmake_vars.insert("Seastar_APPS".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_DEMOS".to_string(), "OFF".to_string());
cmake_vars.insert("Seastar_TESTING".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_API_LEVEL".to_string(), "7".to_string());
cmake_vars.insert("Seastar_DPDK".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_HWLOC".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_NUMA".to_string(), "ON".to_string());
cmake_vars.insert(
"Seastar_C_OR_CPP_DIALECT".to_string(),
"gnu++20".to_string(),
);
cmake_vars.insert(
"Seastar_CXX_FLAGS".to_string(),
"-march=x86-64-v3".to_string(),
);
cmake_vars.insert(
"Seastar_SCHEDULING_GROUPS_COUNT".to_string(),
"16".to_string(),
);
cmake_vars.insert("Seastar_IO_URING".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_CPU_AFFINITY".to_string(), "ON".to_string());
cmake_vars.insert("Seastar_EXCEPTION_HACK".to_string(), "OFF".to_string());
cmake_vars.insert("Seastar_DEBUG_SHARED_PTR".to_string(), "OFF".to_string());
cmake_vars.insert("Seastar_SANITIZE".to_string(), "OFF".to_string());
cmake_vars.insert("Seastar_INSTRUMENT".to_string(), "OFF".to_string());
cmake_vars.insert("Seastar_LD_FLAGS".to_string(), "-fuse-ld=lld".to_string());
cmake_vars.insert("Seastar_DEFAULT_NETWORK".to_string(), "stack".to_string());
cmake_vars.insert(
"Seastar_DEFAULT_ALLOCATOR".to_string(),
"seastar".to_string(),
);
cmake_vars.insert(
"DPDK_INCLUDE_DIR".to_string(),
"/usr/include/dpdk".to_string(),
);
cmake_vars.insert(
"DPDK_LIB_DIR".to_string(),
"/usr/lib/x86_64-linux-gnu/dpdk".to_string(),
);
cmake_vars.insert("CMAKE_CXX_STANDARD".to_string(), "20".to_string());
let mut config = DeepProjectConfig::new(DeepProjectId::ScyllaDb);
config.version = "6.0".to_string();
config.repo_url = "https://github.com/scylladb/seastar.git".to_string();
config.source_subdir = "seastar".to_string();
config.build_system = DeepBuildSystem::Cmake;
config.cmake_vars = cmake_vars;
config.variant = DeepBuildVariant::Release;
config.cxxflags.push("-std=c++20".to_string());
config.cxxflags.push("-march=x86-64-v3".to_string());
config.cxxflags.push("-mtune=znver4".to_string());
config.cxxflags.push("-O3".to_string());
config.cxxflags.push("-fcoroutines".to_string());
config.cxxflags.push("-Wall".to_string());
config.cflags.push("-march=x86-64-v3".to_string());
config.cflags.push("-O3".to_string());
config.simd_level = DeepSimdLevel::Avx2;
config.test_config = Some(DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j16".to_string(),
timeout_secs: 7200,
..Default::default()
});
config
}
pub fn execute_deep_build(
registry: &X86ProjectsDeep,
project_id: DeepProjectId,
) -> io::Result<DeepBuildReport> {
let config = registry.get_project(project_id).ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
format!("Project not registered: {}", project_id.display_name()),
)
})?;
let mut report = DeepBuildReport::new(project_id);
report.start_time = Some(SystemTime::now());
report.status = DeepBuildStatus::Configuring;
let source_dir = registry.project_source_dir(project_id);
let build_dir = registry.project_build_dir(project_id, config.stage);
fs::create_dir_all(&build_dir)?;
if let Some(ref test_config) = config.test_config {
let test_dir = if test_config.test_dir.is_absolute() {
test_config.test_dir.clone()
} else {
build_dir.join(&test_config.test_dir)
};
fs::create_dir_all(&test_dir)?;
}
if let Some(ref build_sys) = registry.build {
if build_sys.auto_patch {
let patched = build_sys.apply_patches(config, &source_dir)?;
if patched > 0 && registry.verbose {
eprintln!(
"Applied {} patches to {}",
patched,
project_id.display_name()
);
}
}
}
let configure_result = configure_project(registry, config, &source_dir, &build_dir)?;
if !configure_result.status.success() {
report.status = DeepBuildStatus::Failed;
report.diagnostics.push(DeepBuildDiagnostic {
severity: X86DiagLevel::Error,
message: format!(
"Configuration failed: {}",
String::from_utf8_lossy(&configure_result.stderr)
),
file: None,
line: None,
column: None,
build_step: "configure".to_string(),
is_known_issue: false,
});
report.end_time = Some(SystemTime::now());
return Ok(report);
}
report.status = DeepBuildStatus::Building;
let build_start = Instant::now();
let build_result = build_project(registry, config, &build_dir)?;
report.duration = build_start.elapsed();
if !build_result.status.success() {
report.status = DeepBuildStatus::Failed;
report.tus_failed = 1; for line in String::from_utf8_lossy(&build_result.stderr).lines() {
if line.contains("error:") {
report.error_count += 1;
report.diagnostics.push(DeepBuildDiagnostic {
severity: X86DiagLevel::Error,
message: line.to_string(),
file: None,
line: None,
column: None,
build_step: "compile".to_string(),
is_known_issue: false,
});
}
}
} else {
report.status = DeepBuildStatus::Success;
}
if let Some(ref build_sys) = registry.build {
match build_sys.generate_compilation_db(config, &build_dir) {
Ok(cdb_path) => {
report.cdb_path = Some(cdb_path);
}
Err(_) => { }
}
}
if report.is_success() {
if let Some(ref test_sys) = registry.test {
if let Some(ref tc) = config.test_config {
if tc.run_after_build {
match test_sys.run_tests(config, &build_dir) {
Ok(test_report) => {
report.test_report = Some(test_report);
}
Err(e) => {
report.diagnostics.push(DeepBuildDiagnostic {
severity: X86DiagLevel::Warning,
message: format!("Test execution failed: {}", e),
file: None,
line: None,
column: None,
build_step: "test".to_string(),
is_known_issue: false,
});
}
}
}
}
}
}
report.end_time = Some(SystemTime::now());
Ok(report)
}
fn configure_project(
registry: &X86ProjectsDeep,
config: &DeepProjectConfig,
source_dir: &Path,
build_dir: &Path,
) -> io::Result<std::process::Output> {
match config.build_system {
DeepBuildSystem::Cmake => configure_cmake_project(registry, config, source_dir, build_dir),
DeepBuildSystem::Autotools => configure_autotools_project(config, source_dir),
DeepBuildSystem::Meson => configure_meson_project(registry, config, source_dir, build_dir),
DeepBuildSystem::Make => configure_make_project(config, source_dir),
DeepBuildSystem::Kbuild => configure_kbuild_project(config, source_dir),
DeepBuildSystem::Bazel => configure_bazel_project(config, source_dir),
DeepBuildSystem::BoostBuild => configure_boost_build_project(config, source_dir),
_ => Err(io::Error::new(
io::ErrorKind::Unsupported,
format!("Build system not implemented: {:?}", config.build_system),
)),
}
}
fn configure_cmake_project(
registry: &X86ProjectsDeep,
config: &DeepProjectConfig,
source_dir: &Path,
build_dir: &Path,
) -> io::Result<std::process::Output> {
let mut cmd = Command::new("cmake");
cmd.arg("-G").arg("Ninja"); cmd.arg("-S").arg(source_dir);
cmd.arg("-B").arg(build_dir);
if let Some(build_type) = config.variant.as_cmake_build_type() {
cmd.arg(format!("-DCMAKE_BUILD_TYPE={}", build_type));
}
cmd.arg(format!(
"-DCMAKE_C_COMPILER={}",
registry.env.get("CC").map_or("clang", |s| s)
));
cmd.arg(format!(
"-DCMAKE_CXX_COMPILER={}",
registry.env.get("CXX").map_or("clang++", |s| s)
));
for (key, value) in ®istry.global_cmake_vars {
cmd.arg(format!("-D{}={}", key, value));
}
for (key, value) in &config.cmake_vars {
cmd.arg(format!("-D{}={}", key, value));
}
let cflags = [&config.cflags[..], ®istry.extra_cflags[..]]
.concat()
.join(" ");
let cxxflags = [&config.cxxflags[..], ®istry.extra_cxxflags[..]]
.concat()
.join(" ");
let ldflags = [&config.ldflags[..], ®istry.extra_ldflags[..]]
.concat()
.join(" ");
if !cflags.is_empty() {
cmd.arg(format!("-DCMAKE_C_FLAGS={}", cflags));
}
if !cxxflags.is_empty() {
cmd.arg(format!("-DCMAKE_CXX_FLAGS={}", cxxflags));
}
if !ldflags.is_empty() {
cmd.arg(format!("-DCMAKE_EXE_LINKER_FLAGS={}", ldflags));
cmd.arg(format!("-DCMAKE_SHARED_LINKER_FLAGS={}", ldflags));
}
let mut env_vars = registry.env.clone();
for (key, value) in &config.env_overrides {
env_vars.insert(key.clone(), value.clone());
}
for (key, value) in &env_vars {
cmd.env(key, value);
}
cmd.output()
}
fn configure_autotools_project(
config: &DeepProjectConfig,
source_dir: &Path,
) -> io::Result<std::process::Output> {
let configure_script = source_dir.join("configure");
let mut cmd = if configure_script.exists() {
Command::new(&configure_script)
} else {
let autoreconf = Command::new("autoreconf")
.arg("-fi")
.current_dir(source_dir)
.output();
let script = source_dir.join("configure");
if !script.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("configure script not found in {}", source_dir.display()),
));
}
Command::new(&script)
};
cmd.current_dir(source_dir);
for flag in &config.configure_flags {
if flag.contains(' ') {
let parts: Vec<&str> = flag.splitn(2, ' ').collect();
if parts.len() == 2 {
cmd.arg(parts[0]).arg(parts[1]);
}
} else {
cmd.arg(flag);
}
}
let cflags = config.cflags.join(" ");
let cxxflags = config.cxxflags.join(" ");
let ldflags = config.ldflags.join(" ");
if !cflags.is_empty() {
cmd.env("CFLAGS", &cflags);
}
if !cxxflags.is_empty() {
cmd.env("CXXFLAGS", &cxxflags);
}
if !ldflags.is_empty() {
cmd.env("LDFLAGS", &ldflags);
}
cmd.output()
}
fn configure_meson_project(
registry: &X86ProjectsDeep,
config: &DeepProjectConfig,
source_dir: &Path,
build_dir: &Path,
) -> io::Result<std::process::Output> {
let mut cmd = Command::new("meson");
cmd.arg("setup");
cmd.arg(build_dir);
cmd.arg(source_dir);
cmd.arg(format!("--buildtype={}", config.variant.as_str()));
cmd.arg(format!(
"--prefix={}",
registry.project_install_dir(config.id).display()
));
for option in &config.meson_options {
cmd.arg(format!("-D{}", option));
}
let cflags = config.cflags.join(" ");
let cxxflags = config.cxxflags.join(" ");
if !cflags.is_empty() {
cmd.env("CFLAGS", &cflags);
}
if !cxxflags.is_empty() {
cmd.env("CXXFLAGS", &cxxflags);
}
cmd.output()
}
fn configure_make_project(
config: &DeepProjectConfig,
source_dir: &Path,
) -> io::Result<std::process::Output> {
let makefile = source_dir.join("Makefile");
if !makefile.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Makefile not found in {}", source_dir.display()),
));
}
let mut out = std::process::Output {
status: std::process::ExitStatus::default(),
stdout: Vec::new(),
stderr: Vec::new(),
};
Ok(out)
}
fn configure_kbuild_project(
config: &DeepProjectConfig,
source_dir: &Path,
) -> io::Result<std::process::Output> {
let mut cmd = Command::new("make");
cmd.arg("defconfig");
cmd.arg(format!(
"ARCH={}",
if config.cflags.iter().any(|f| f == "-m32") {
"i386"
} else {
"x86_64"
}
));
cmd.env("CC", "clang");
cmd.env("LD", "ld.lld");
cmd.current_dir(source_dir);
cmd.output()
}
fn configure_bazel_project(
config: &DeepProjectConfig,
source_dir: &Path,
) -> io::Result<std::process::Output> {
Command::new("bazel")
.arg("sync")
.current_dir(source_dir)
.output()
}
fn configure_boost_build_project(
config: &DeepProjectConfig,
source_dir: &Path,
) -> io::Result<std::process::Output> {
let bootstrap = source_dir.join("bootstrap.sh");
if bootstrap.exists() {
Command::new(&bootstrap)
.arg("--with-toolset=clang")
.current_dir(source_dir)
.output()
} else {
Ok(std::process::Output {
status: std::process::ExitStatus::default(),
stdout: Vec::new(),
stderr: Vec::new(),
})
}
}
fn build_project(
registry: &X86ProjectsDeep,
config: &DeepProjectConfig,
build_dir: &Path,
) -> io::Result<std::process::Output> {
match config.build_system {
DeepBuildSystem::Cmake => {
let mut cmd = Command::new("cmake");
cmd.arg("--build").arg(build_dir);
if registry.parallel_jobs > 0 {
cmd.arg("-j").arg(registry.parallel_jobs.to_string());
}
cmd.output()
}
DeepBuildSystem::Make => {
let mut cmd = Command::new("make");
if registry.parallel_jobs > 0 {
cmd.arg("-j").arg(registry.parallel_jobs.to_string());
}
cmd.current_dir(build_dir);
cmd.output()
}
DeepBuildSystem::Autotools => {
let mut cmd = Command::new("make");
if registry.parallel_jobs > 0 {
cmd.arg("-j").arg(registry.parallel_jobs.to_string());
}
cmd.current_dir(build_dir);
cmd.output()
}
DeepBuildSystem::Meson => Command::new("meson")
.arg("compile")
.arg("-C")
.arg(build_dir)
.output(),
DeepBuildSystem::Ninja => {
let mut cmd = Command::new("ninja");
if registry.parallel_jobs > 0 {
cmd.arg("-j").arg(registry.parallel_jobs.to_string());
}
cmd.current_dir(build_dir);
cmd.output()
}
DeepBuildSystem::Kbuild => {
let mut cmd = Command::new("make");
if registry.parallel_jobs > 0 {
cmd.arg("-j").arg(registry.parallel_jobs.to_string());
}
cmd.arg("bzImage");
cmd.arg("modules");
cmd.env("CC", "clang");
cmd.env("LD", "ld.lld");
cmd.current_dir(build_dir);
cmd.output()
}
DeepBuildSystem::Bazel => Command::new("bazel")
.arg("build")
.arg("//...")
.current_dir(build_dir)
.output(),
DeepBuildSystem::BoostBuild => {
let mut cmd = Command::new("./b2");
if registry.parallel_jobs > 0 {
cmd.arg(format!("-j{}", registry.parallel_jobs));
}
cmd.current_dir(build_dir);
cmd.output()
}
_ => Err(io::Error::new(
io::ErrorKind::Unsupported,
format!("Build not implemented for {:?}", config.build_system),
)),
}
}
pub fn build_all_projects(registry: &X86ProjectsDeep) -> Vec<DeepBuildReport> {
let order = registry.build_order();
let mut reports = Vec::new();
for project_id in order {
if let Some(ref build_sys) = registry.build {
if build_sys.is_cancelled() {
let mut report = DeepBuildReport::new(project_id);
report.status = DeepBuildStatus::Cancelled;
reports.push(report);
continue;
}
}
match execute_deep_build(registry, project_id) {
Ok(report) => {
let success = report.is_success();
reports.push(report);
if !success && registry.stop_on_error {
break;
}
}
Err(e) => {
let mut report = DeepBuildReport::new(project_id);
report.status = DeepBuildStatus::Failed;
report.diagnostics.push(DeepBuildDiagnostic {
severity: X86DiagLevel::Fatal,
message: format!("Build execution error: {}", e),
file: None,
line: None,
column: None,
build_step: "execute".to_string(),
is_known_issue: false,
});
reports.push(report);
if registry.stop_on_error {
break;
}
}
}
}
reports
}
pub fn test_all_projects(registry: &X86ProjectsDeep) -> BTreeMap<DeepProjectId, DeepTestReport> {
let mut results = BTreeMap::new();
for (project_id, report) in ®istry.results {
if !report.is_success() {
continue;
}
let config = match registry.get_project(*project_id) {
Some(c) => c,
None => continue,
};
let build_dir = registry.project_build_dir(*project_id, config.stage);
if let Some(ref test_sys) = registry.test {
match test_sys.run_tests(config, &build_dir) {
Ok(test_report) => {
results.insert(*project_id, test_report);
}
Err(e) => {
let mut tr = DeepTestReport::new(*project_id);
tr.raw_output = format!("Error: {}", e);
results.insert(*project_id, tr);
}
}
}
}
results
}
pub fn detect_host_cpu_features() -> Vec<String> {
let mut features = Vec::new();
if let Ok(content) = fs::read_to_string("/proc/cpuinfo") {
if let Some(flags_line) = content.lines().find(|l| l.starts_with("flags")) {
if let Some(flags_str) = flags_line.split(':').nth(1) {
for flag in flags_str.split_whitespace() {
let upper = flag.to_uppercase();
if X86_CPU_FEATURES.iter().any(|f| f.to_uppercase() == upper) {
features.push(flag.to_lowercase());
}
}
}
}
}
if !features.iter().any(|f| f == "sse2") {
features.push("sse2".to_string());
}
features.sort();
features.dedup();
features
}
pub fn build_summary(reports: &[DeepBuildReport]) -> String {
let total = reports.len();
let successful = reports.iter().filter(|r| r.is_success()).count();
let failed = reports
.iter()
.filter(|r| r.status == DeepBuildStatus::Failed)
.count();
let skipped = reports
.iter()
.filter(|r| r.status == DeepBuildStatus::Skipped)
.count();
let cancelled = reports
.iter()
.filter(|r| r.status == DeepBuildStatus::Cancelled)
.count();
let total_duration: Duration = reports.iter().map(|r| r.elapsed()).sum();
let total_tus: usize = reports.iter().map(|r| r.tus_compiled).sum();
let total_warnings: usize = reports.iter().map(|r| r.warning_count).sum();
let total_errors: usize = reports.iter().map(|r| r.error_count).sum();
format!(
"Deep Build Summary\n\
===================\n\
Projects: {} total, {} succeeded, {} failed, {} skipped, {} cancelled\n\
Translation units: {} compiled\n\
Warnings: {}\n\
Errors: {}\n\
Total time: {:.1}s\n",
total,
successful,
failed,
skipped,
cancelled,
total_tus,
total_warnings,
total_errors,
total_duration.as_secs_f64(),
)
}
pub fn test_summary(test_results: &BTreeMap<DeepProjectId, DeepTestReport>) -> String {
let mut total = 0usize;
let mut passed = 0usize;
let mut failed = 0usize;
let mut skipped = 0usize;
for report in test_results.values() {
total += report.total;
passed += report.passed;
failed += report.failed;
skipped += report.skipped;
}
format!(
"Test Summary\n\
=============\n\
Projects tested: {}\n\
Tests: {} total, {} passed, {} failed, {} skipped\n\
Pass rate: {:.1}%\n",
test_results.len(),
total,
passed,
failed,
skipped,
if total > 0 {
passed as f64 / total as f64 * 100.0
} else {
0.0
},
)
}
pub fn default_release_opt_config() -> DeepOptConfig {
DeepOptConfig {
enable_thin_lto: true,
enable_fmv: true,
..Default::default()
}
}
pub fn aggressive_opt_config() -> DeepOptConfig {
DeepOptConfig {
enable_pgo: true,
pgo_training_iters: 5,
use_cs_pgo: true,
enable_thin_lto: true,
enable_bolt: true,
bolt_mode: "hfsort+".to_string(),
enable_fmv: true,
..Default::default()
}
}
pub fn generate_cmake_presets(registry: &X86ProjectsDeep) -> String {
let mut json = String::from("{\n \"version\": 6,\n \"configurePresets\": [\n");
for (i, (id, config)) in registry.projects.iter().enumerate() {
if i > 0 {
json.push_str(",\n");
}
let build_dir = registry.project_build_dir(*id, config.stage);
json.push_str(&format!(
" {{\n\
\"name\": \"{}-{}\",\n\
\"displayName\": \"{} {}\",\n\
\"binaryDir\": \"{}\",\n\
\"generator\": \"Ninja\",\n\
\"cacheVariables\": {{\n\
\"CMAKE_BUILD_TYPE\": \"{}\",\n\
\"CMAKE_C_COMPILER\": \"clang\",\n\
\"CMAKE_CXX_COMPILER\": \"clang++\"\n\
}}\n\
}}",
id.as_str(),
config.variant.as_str(),
config.name,
config.variant.as_str(),
build_dir.display(),
config.variant.as_cmake_build_type().unwrap_or("Release"),
));
}
json.push_str("\n ]\n}\n");
json
}
#[derive(Debug, Clone)]
pub struct ExtendedBenchmarkConfig {
pub suite: String,
pub iterations: usize,
pub min_time_secs: f64,
pub warmup: bool,
pub warmup_iterations: usize,
pub cpu_pinning: bool,
pub cpu_core: usize,
pub drop_caches: bool,
pub use_perf: bool,
pub perf_events: Vec<String>,
pub output_format: BenchOutputFormat,
pub compare_baseline: bool,
pub baseline_path: Option<PathBuf>,
pub max_regression_pct: f64,
}
impl Default for ExtendedBenchmarkConfig {
fn default() -> Self {
Self {
suite: "default".to_string(),
iterations: 10,
min_time_secs: 1.0,
warmup: true,
warmup_iterations: 3,
cpu_pinning: true,
cpu_core: 0,
drop_caches: false,
use_perf: false,
perf_events: vec![
"cycles".into(),
"instructions".into(),
"cache-misses".into(),
],
output_format: BenchOutputFormat::Json,
compare_baseline: true,
baseline_path: None,
max_regression_pct: 5.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BenchOutputFormat {
Json,
Csv,
ConsoleTable,
GoogleBenchmark,
}
#[derive(Debug, Clone)]
pub struct BenchMeasurement {
pub name: String,
pub iterations: usize,
pub real_time_ns: u64,
pub cpu_time_ns: u64,
pub time_unit: String,
pub bytes_per_second: u64,
pub items_per_second: u64,
pub counters: HashMap<String, f64>,
pub label: Option<String>,
}
pub fn run_extended_benchmark(
binary: &Path,
config: &ExtendedBenchmarkConfig,
) -> io::Result<Vec<BenchMeasurement>> {
let mut measurements = Vec::new();
if !binary.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Benchmark binary not found: {}", binary.display()),
));
}
let mut cmd = Command::new(binary);
cmd.arg(format!("--benchmark_min_time={}", config.min_time_secs));
cmd.arg(format!("--benchmark_repetitions={}", config.iterations));
if config.warmup {
cmd.arg("--benchmark_enable_random_interleaving=true");
}
match config.output_format {
BenchOutputFormat::Json => {
cmd.arg("--benchmark_format=json");
}
BenchOutputFormat::Csv => {
cmd.arg("--benchmark_format=csv");
}
BenchOutputFormat::ConsoleTable => {
cmd.arg("--benchmark_format=console");
}
BenchOutputFormat::GoogleBenchmark => {
}
}
if config.use_perf {
let mut perf_cmd = Command::new("perf");
perf_cmd.arg("stat");
for event in &config.perf_events {
perf_cmd.arg("-e").arg(event);
}
perf_cmd.arg(binary);
let output = perf_cmd.output()?;
let stderr = String::from_utf8_lossy(&output.stderr);
for line in stderr.lines() {
if line.contains("time elapsed") {
}
}
}
let output = cmd.output()?;
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
if line.starts_with("BM_") {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 3 {
let name = parts[0].to_string();
let real_time: u64 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
let cpu_time: u64 = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
measurements.push(BenchMeasurement {
name,
iterations: config.iterations,
real_time_ns: real_time,
cpu_time_ns: cpu_time,
time_unit: "ns".to_string(),
bytes_per_second: 0,
items_per_second: 0,
counters: HashMap::new(),
label: None,
});
}
}
}
Ok(measurements)
}
pub fn analyze_benchmark_results(
name: &str,
results: &[BenchMeasurement],
baseline: Option<&[BenchMeasurement]>,
) -> String {
let mut report = format!(
"Benchmark Analysis: {}
",
name
);
report.push_str(
"==========================================
",
);
for result in results {
let baseline_ns = baseline.and_then(|b| {
b.iter()
.find(|bm| bm.name == result.name)
.map(|bm| bm.real_time_ns)
});
report.push_str(&format!("{}: {:>12} ns", result.name, result.real_time_ns));
if let Some(base_ns) = baseline_ns {
if base_ns > 0 {
let delta_pct =
(result.real_time_ns as f64 - base_ns as f64) / base_ns as f64 * 100.0;
let icon = if delta_pct > 5.0 {
"🔴 REGRESSION"
} else if delta_pct < -1.0 {
"🟢 IMPROVEMENT"
} else {
"⚪"
};
report.push_str(&format!(" ({:+.1}% vs baseline) {}", delta_pct, icon));
}
}
report.push('\n');
}
report
}
#[derive(Debug, Clone)]
pub struct StaticAnalysisConfig {
pub run_clang_tidy: bool,
pub tidy_checks: Vec<String>,
pub run_scan_build: bool,
pub run_iwyu: bool,
pub warnings_as_errors: bool,
pub include_patterns: Vec<String>,
pub exclude_patterns: Vec<String>,
pub output_dir: PathBuf,
pub max_findings_per_check: usize,
}
impl Default for StaticAnalysisConfig {
fn default() -> Self {
Self {
run_clang_tidy: true,
tidy_checks: vec![
"clang-analyzer-*".into(),
"bugprone-*".into(),
"modernize-*".into(),
"performance-*".into(),
"readability-*".into(),
],
run_scan_build: false,
run_iwyu: false,
warnings_as_errors: true,
include_patterns: vec!["src/**/*.cpp".into(), "src/**/*.c".into()],
exclude_patterns: vec!["**/test/**".into(), "**/third_party/**".into()],
output_dir: PathBuf::from("analysis-reports"),
max_findings_per_check: 50,
}
}
}
#[derive(Debug, Clone)]
pub struct StaticAnalysisResult {
pub total_findings: usize,
pub errors: usize,
pub warnings: usize,
pub notes: usize,
pub findings: Vec<StaticAnalysisFinding>,
pub duration: Duration,
pub tool_outputs: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct StaticAnalysisFinding {
pub tool: String,
pub check_name: String,
pub file: PathBuf,
pub line: u32,
pub column: u32,
pub message: String,
pub severity: FindingSeverity,
pub fixit: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FindingSeverity {
Note,
Warning,
Error,
Fatal,
}
pub fn run_static_analysis(
config: &StaticAnalysisConfig,
source_dir: &Path,
build_dir: &Path,
) -> io::Result<StaticAnalysisResult> {
let mut result = StaticAnalysisResult {
total_findings: 0,
errors: 0,
warnings: 0,
notes: 0,
findings: Vec::new(),
duration: Duration::ZERO,
tool_outputs: HashMap::new(),
};
let start = Instant::now();
fs::create_dir_all(&config.output_dir)?;
if config.run_clang_tidy {
let checks = config.tidy_checks.join(",");
let tidy_output = config.output_dir.join("clang-tidy.txt");
let cdb = build_dir.join("compile_commands.json");
if cdb.exists() {
let output = Command::new("run-clang-tidy")
.arg("-p")
.arg(build_dir)
.arg(&format!("-checks={}", checks))
.arg(&format!("-export-fixes={}", tidy_output.display()))
.arg("-j")
.arg(num_cpus::get().to_string())
.output()?;
let stdout = String::from_utf8_lossy(&output.stdout);
result
.tool_outputs
.insert("clang-tidy".to_string(), stdout.to_string());
for line in stdout.lines() {
if line.contains("warning:") || line.contains("error:") {
result.total_findings += 1;
if line.contains("error:") {
result.errors += 1;
} else {
result.warnings += 1;
}
}
}
}
}
if config.run_scan_build {
let output = Command::new("scan-build")
.arg("-o")
.arg(&config.output_dir)
.arg("cmake")
.arg("--build")
.arg(build_dir)
.output()?;
result.tool_outputs.insert(
"scan-build".to_string(),
String::from_utf8_lossy(&output.stdout).to_string(),
);
}
if config.run_iwyu {
let output = Command::new("include-what-you-use")
.arg("-Xiwyu")
.arg("--mapping_file=/usr/share/include-what-you-use/iwyu.gcc.imp")
.arg("src/main.cpp")
.output()?;
result.tool_outputs.insert(
"iwyu".to_string(),
String::from_utf8_lossy(&output.stdout).to_string(),
);
}
result.duration = start.elapsed();
Ok(result)
}
pub fn detect_system_memory_mb() -> u64 {
8192
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86TargetOs {
Linux,
Windows,
FreeBsd,
Android,
Darwin,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86DataModel {
Lp64,
Ilp32,
Llp64,
}
#[derive(Debug, Clone)]
pub struct X86CrossTarget {
pub triple: String,
pub cpu: String,
pub os: X86TargetOs,
pub abi: String,
pub is_32bit: bool,
pub data_model: X86DataModel,
pub default_cflags: Vec<String>,
pub default_ldflags: Vec<String>,
pub min_features: Vec<String>,
pub stack_alignment: u32,
pub red_zone_size: u32,
pub page_size: u32,
pub default_pic: bool,
}
impl X86CrossTarget {
pub fn x86_64_linux_gnu() -> Self {
Self {
triple: "x86_64-unknown-linux-gnu".into(),
cpu: "x86-64".into(),
os: X86TargetOs::Linux,
abi: "gnu".into(),
is_32bit: false,
data_model: X86DataModel::Lp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec![],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 128,
page_size: 4096,
default_pic: true,
}
}
pub fn i686_linux_gnu() -> Self {
Self {
triple: "i686-unknown-linux-gnu".into(),
cpu: "i686".into(),
os: X86TargetOs::Linux,
abi: "gnu".into(),
is_32bit: true,
data_model: X86DataModel::Ilp32,
default_cflags: vec!["-m32".into()],
default_ldflags: vec![],
min_features: vec!["mmx".into()],
stack_alignment: 16,
red_zone_size: 0,
page_size: 4096,
default_pic: true,
}
}
pub fn x86_64_windows_msvc() -> Self {
Self {
triple: "x86_64-pc-windows-msvc".into(),
cpu: "x86-64".into(),
os: X86TargetOs::Windows,
abi: "msvc".into(),
is_32bit: false,
data_model: X86DataModel::Llp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec!["-fuse-ld=lld".into()],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 0,
page_size: 4096,
default_pic: false,
}
}
pub fn x86_64_darwin() -> Self {
Self {
triple: "x86_64-apple-darwin".into(),
cpu: "x86-64".into(),
os: X86TargetOs::Darwin,
abi: "".into(),
is_32bit: false,
data_model: X86DataModel::Lp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec![],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 128,
page_size: 4096,
default_pic: true,
}
}
}
pub fn x86_toolchain_database() -> Vec<X86CrossTarget> {
vec![
X86CrossTarget::x86_64_linux_gnu(),
X86CrossTarget::i686_linux_gnu(),
X86CrossTarget::x86_64_windows_msvc(),
X86CrossTarget::x86_64_darwin(),
X86CrossTarget {
triple: "x86_64-unknown-linux-musl".to_string(),
cpu: "x86-64".to_string(),
os: X86TargetOs::Linux,
abi: "musl".to_string(),
is_32bit: false,
data_model: X86DataModel::Lp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec!["-static".into()],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 128,
page_size: 4096,
default_pic: true,
},
X86CrossTarget {
triple: "i686-unknown-linux-musl".to_string(),
cpu: "i686".to_string(),
os: X86TargetOs::Linux,
abi: "musl".to_string(),
is_32bit: true,
data_model: X86DataModel::Ilp32,
default_cflags: vec!["-m32".into()],
default_ldflags: vec!["-static".into()],
min_features: vec!["mmx".into()],
stack_alignment: 16,
red_zone_size: 0,
page_size: 4096,
default_pic: true,
},
X86CrossTarget {
triple: "x86_64-pc-windows-gnu".to_string(),
cpu: "x86-64".to_string(),
os: X86TargetOs::Windows,
abi: "gnu".to_string(),
is_32bit: false,
data_model: X86DataModel::Llp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec!["-fuse-ld=lld".into()],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 0,
page_size: 4096,
default_pic: false,
},
X86CrossTarget {
triple: "x86_64-unknown-freebsd".to_string(),
cpu: "x86-64".to_string(),
os: X86TargetOs::FreeBsd,
abi: "".to_string(),
is_32bit: false,
data_model: X86DataModel::Lp64,
default_cflags: vec!["-m64".into()],
default_ldflags: vec!["-fuse-ld=lld".into()],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 128,
page_size: 4096,
default_pic: true,
},
X86CrossTarget {
triple: "x86_64-linux-android".to_string(),
cpu: "x86-64".to_string(),
os: X86TargetOs::Android,
abi: "".to_string(),
is_32bit: false,
data_model: X86DataModel::Lp64,
default_cflags: vec!["-m64".into(), "-fPIE".into()],
default_ldflags: vec!["-fuse-ld=lld".into(), "-pie".into()],
min_features: vec!["sse2".into()],
stack_alignment: 16,
red_zone_size: 128,
page_size: 4096,
default_pic: true,
},
]
}
pub fn find_toolchain(triple: &str) -> Option<X86CrossTarget> {
x86_toolchain_database()
.into_iter()
.find(|t| t.triple == triple)
}
pub fn known_triples() -> Vec<String> {
x86_toolchain_database()
.into_iter()
.map(|t| t.triple)
.collect()
}
#[derive(Debug, Clone)]
pub struct BuildProfiler {
pub project_id: DeepProjectId,
pub configurations: Vec<ProfiledConfiguration>,
pub best_config: Option<ProfiledConfiguration>,
}
#[derive(Debug, Clone)]
pub struct ProfiledConfiguration {
pub flags: Vec<String>,
pub build_time_secs: f64,
pub binary_size_bytes: u64,
pub runtime_perf_ns_per_iter: u64,
pub score: f64, }
impl BuildProfiler {
pub fn new(project_id: DeepProjectId) -> Self {
Self {
project_id,
configurations: Vec::new(),
best_config: None,
}
}
pub fn add_result(
&mut self,
flags: &[String],
build_time_secs: f64,
binary_size_bytes: u64,
runtime_ns: u64,
) {
let score = 1.0 / (build_time_secs + 1.0) * 0.3
+ 1.0 / (binary_size_bytes as f64 / 1_000_000.0 + 1.0) * 0.2
+ 1.0 / (runtime_ns as f64 / 1_000_000.0 + 1.0) * 0.5;
self.configurations.push(ProfiledConfiguration {
flags: flags.to_vec(),
build_time_secs,
binary_size_bytes,
runtime_perf_ns_per_iter: runtime_ns,
score,
});
}
pub fn evaluate(&mut self) -> Option<&ProfiledConfiguration> {
self.configurations.sort_by(|a, b| {
b.score
.partial_cmp(&a.score)
.unwrap_or(std::cmp::Ordering::Equal)
});
self.best_config = self.configurations.first().cloned();
self.best_config.as_ref()
}
pub fn report(&self) -> String {
let mut r = format!(
"Build Profiling Report: {}
",
self.project_id.display_name()
);
r.push_str(
"=============================================
",
);
r.push_str(&format!(
"{:<4} {:<60} {:<10} {:<12} {:<12} {:<8}
",
"Rank", "Flags", "Build(s)", "Size(MB)", "Runtime(ns)", "Score"
));
r.push_str("---- ------------------------------------------------------------ --------- ------------ ------------ -------
");
for (i, config) in self.configurations.iter().enumerate() {
let flags_str = config.flags.join(" ");
let truncated = if flags_str.len() > 58 {
format!("{}...", &flags_str[..55])
} else {
flags_str
};
r.push_str(&format!(
"{:<4} {:<60} {:<10.1} {:<12.1} {:<12} {:<8.4}
",
i + 1,
truncated,
config.build_time_secs,
config.binary_size_bytes as f64 / 1_048_576.0,
config.runtime_perf_ns_per_iter,
config.score,
));
}
if let Some(ref best) = self.best_config {
r.push_str(&format!(
"
Best configuration: {}
",
best.flags.join(" ")
));
}
r
}
}
pub fn standard_test_configs() -> Vec<DeepTestConfig> {
vec![
DeepTestConfig {
run_after_build: true,
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j4".to_string(),
parallel: true,
parallel_workers: 4,
output_format: DeepTestOutputFormat::JunitXml,
..Default::default()
},
DeepTestConfig {
run_after_build: true,
test_framework: DeepTestFramework::GTest,
test_command: "".to_string(), parallel: true,
parallel_workers: 8,
output_format: DeepTestOutputFormat::Json,
..Default::default()
},
DeepTestConfig {
run_after_build: true,
test_framework: DeepTestFramework::Catch2,
test_command: "".to_string(),
parallel: true,
parallel_workers: 8,
output_format: DeepTestOutputFormat::JunitXml,
..Default::default()
},
]
}
pub fn default_ctest_config() -> DeepTestConfig {
DeepTestConfig {
test_framework: DeepTestFramework::Ctest,
test_command: "ctest --output-on-failure -j16".to_string(),
test_dir: PathBuf::from("build"),
run_after_build: true,
..Default::default()
}
}
pub fn default_gtest_config() -> DeepTestConfig {
DeepTestConfig {
test_framework: DeepTestFramework::GTest,
test_command: "".to_string(),
test_dir: PathBuf::from("build"),
run_after_build: true,
output_format: DeepTestOutputFormat::Json,
..Default::default()
}
}
pub fn export_build_report(report: &DeepBuildReport, format: &str) -> String {
match format {
"json" => report.to_json(),
"markdown" => {
let mut md = format!(
"# Build Report: {}
",
report.project_id.display_name()
);
md.push_str(&format!(
"- **Status**: {}
",
report.status
));
md.push_str(&format!(
"- **TUs Compiled**: {}
",
report.tus_compiled
));
md.push_str(&format!(
"- **TUs Failed**: {}
",
report.tus_failed
));
md.push_str(&format!(
"- **Warnings**: {}
",
report.warning_count
));
md.push_str(&format!(
"- **Errors**: {}
",
report.error_count
));
md.push_str(&format!(
"- **Duration**: {:.1}s
",
report.elapsed().as_secs_f64()
));
md.push_str(&format!(
"- **Output Size**: {} bytes
",
report.output_size_bytes
));
if !report.diagnostics.is_empty() {
md.push_str(
"
## Diagnostics
",
);
for diag in &report.diagnostics {
md.push_str(&format!(
"- [{}] {}
",
diag.severity, diag.message
));
}
}
if let Some(ref test_report) = report.test_report {
md.push_str(
"
## Test Results
",
);
md.push_str(&format!(
"- **Passed**: {}/{}
",
test_report.passed, test_report.total
));
md.push_str(&format!(
"- **Failed**: {}
",
test_report.failed
));
md.push_str(&format!(
"- **Skipped**: {}
",
test_report.skipped
));
}
if let Some(ref opt_report) = report.opt_report {
md.push_str(
"
## Optimizations
",
);
md.push_str(&opt_report.summary());
md.push('\n');
}
md
}
"text" => report.summary(),
_ => report.summary(),
}
}
pub fn export_test_report(report: &DeepTestReport, format: &str) -> String {
match format {
"json" => format!(
"{{\"project\":\"{}\",\"total\":{},\"passed\":{},\"failed\":{},\"skipped\":{},\"flaky\":{},\"duration_secs\":{:.3}}}",
report.project_id.as_str(),
report.total, report.passed, report.failed,
report.skipped, report.flaky,
report.duration.as_secs_f64(),
),
"junit" => {
let mut xml = String::from(
r#"<?xml version="1.0" encoding="UTF-8"?>
"#,
);
xml.push_str(&format!(r#"<testsuite name="{}" tests="{}" failures="{}" errors="0" skipped="{}" time="{:.3}">
"#,
report.project_id.as_str(), report.total, report.failed,
report.skipped, report.duration.as_secs_f64()));
for case in &report.cases {
xml.push_str(&format!(
r#" <testcase classname="{}" name="{}" time="{:.3}">
"#,
case.suite,
case.name,
case.duration.as_secs_f64(),
));
if !case.passed {
xml.push_str(&format!(
r#" <failure message="{}" />
"#,
case.failure_message.as_deref().unwrap_or("unknown")
));
}
if case.skipped {
xml.push_str(" <skipped />\n");
}
xml.push_str(" </testcase>\n");
}
xml.push_str("</testsuite>\n");
xml
}
"markdown" => report.summary(),
_ => report.summary(),
}
}
#[derive(Debug, Clone)]
pub struct ProjectScanResult {
pub detected_projects: Vec<DetectedProject>,
pub scan_duration: Duration,
pub directories_scanned: usize,
}
#[derive(Debug, Clone)]
pub struct DetectedProject {
pub project_id: DeepProjectId,
pub path: PathBuf,
pub confidence: f64, pub detected_version: Option<String>,
pub evidence: Vec<String>,
}
pub fn scan_for_projects(root: &Path) -> io::Result<ProjectScanResult> {
let start = Instant::now();
let mut detected = Vec::new();
let mut dirs_scanned = 0usize;
if root.is_dir() {
if root.join("llvm").join("CMakeLists.txt").exists() {
if let Ok(content) = fs::read_to_string(root.join("llvm").join("CMakeLists.txt")) {
let version = content
.lines()
.find(|l| l.contains("LLVM_VERSION_MAJOR"))
.and_then(|l| l.split_whitespace().last().map(|s| s.to_string()));
detected.push(DetectedProject {
project_id: DeepProjectId::Llvm,
path: root.join("llvm"),
confidence: 0.95,
detected_version: version,
evidence: vec!["Found llvm/CMakeLists.txt".into()],
});
}
}
if root.join("Makefile").exists() {
if let Ok(content) = fs::read_to_string(root.join("Makefile")) {
if content.contains("KERNELRELEASE") || content.contains("linux") {
detected.push(DetectedProject {
project_id: DeepProjectId::LinuxKernel,
path: root.to_path_buf(),
confidence: 0.90,
detected_version: None,
evidence: vec!["Found Linux kernel Makefile".into()],
});
}
}
}
if root.join("CMakeLists.txt").exists() {
if let Ok(content) = fs::read_to_string(root.join("CMakeLists.txt")) {
let signatures: Vec<(DeepProjectId, &str, f64)> = vec![
(DeepProjectId::Qt, "find_package(Qt", 0.85),
(DeepProjectId::OpenCV, "find_package(OpenCV", 0.90),
(DeepProjectId::Protobuf, "protobuf", 0.90),
(DeepProjectId::Grpc, "gRPC", 0.90),
(DeepProjectId::Abseil, "absl", 0.90),
(DeepProjectId::LevelDb, "leveldb", 0.90),
(DeepProjectId::RocksDb, "rocksdb", 0.90),
(DeepProjectId::DuckDb, "duckdb", 0.90),
(DeepProjectId::ClickHouse, "clickhouse", 0.90),
(DeepProjectId::TensorFlowLite, "tensorflow", 0.85),
(DeepProjectId::ScyllaDb, "seastar", 0.85),
];
for (id, sig, conf) in signatures {
if content.contains(sig) {
detected.push(DetectedProject {
project_id: id,
path: root.to_path_buf(),
confidence: conf,
detected_version: None,
evidence: vec![format!("Found signature: {}", sig)],
});
}
}
}
}
dirs_scanned += 1;
if let Ok(entries) = fs::read_dir(root) {
for entry in entries.flatten() {
if entry.path().is_dir() {
dirs_scanned += 1;
}
}
}
}
Ok(ProjectScanResult {
detected_projects: detected,
scan_duration: start.elapsed(),
directories_scanned: dirs_scanned,
})
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
fn test_registry() -> X86ProjectsDeep {
let tmp = env::temp_dir().join("llvm-native-test-projects-deep");
let _ = fs::create_dir_all(&tmp);
X86ProjectsDeep::new(&tmp)
}
#[test]
fn test_deep_project_id_from_str() {
assert_eq!(DeepProjectId::from_str("llvm"), Some(DeepProjectId::Llvm));
assert_eq!(DeepProjectId::from_str("Clang"), Some(DeepProjectId::Llvm));
assert_eq!(
DeepProjectId::from_str("linux-kernel"),
Some(DeepProjectId::LinuxKernel)
);
assert_eq!(DeepProjectId::from_str("qt"), Some(DeepProjectId::Qt));
assert_eq!(DeepProjectId::from_str("boost"), Some(DeepProjectId::Boost));
assert_eq!(
DeepProjectId::from_str("FFmpeg"),
Some(DeepProjectId::Ffmpeg)
);
assert_eq!(
DeepProjectId::from_str("opencv"),
Some(DeepProjectId::OpenCV)
);
assert_eq!(
DeepProjectId::from_str("tflite"),
Some(DeepProjectId::TensorFlowLite)
);
assert_eq!(
DeepProjectId::from_str("protobuf"),
Some(DeepProjectId::Protobuf)
);
assert_eq!(DeepProjectId::from_str("grpc"), Some(DeepProjectId::Grpc));
assert_eq!(DeepProjectId::from_str("absl"), Some(DeepProjectId::Abseil));
assert_eq!(
DeepProjectId::from_str("leveldb"),
Some(DeepProjectId::LevelDb)
);
assert_eq!(
DeepProjectId::from_str("rocksdb"),
Some(DeepProjectId::RocksDb)
);
assert_eq!(
DeepProjectId::from_str("duckdb"),
Some(DeepProjectId::DuckDb)
);
assert_eq!(
DeepProjectId::from_str("clickhouse"),
Some(DeepProjectId::ClickHouse)
);
assert_eq!(
DeepProjectId::from_str("seastar"),
Some(DeepProjectId::ScyllaDb)
);
assert_eq!(DeepProjectId::from_str("nonexistent"), None);
}
#[test]
fn test_deep_project_id_display_name() {
assert_eq!(DeepProjectId::Llvm.display_name(), "LLVM/Clang");
assert_eq!(DeepProjectId::LinuxKernel.display_name(), "Linux Kernel");
assert_eq!(DeepProjectId::ScyllaDb.display_name(), "ScyllaDB/Seastar");
}
#[test]
fn test_build_variant_cmake_type() {
assert_eq!(DeepBuildVariant::Debug.as_cmake_build_type(), Some("Debug"));
assert_eq!(
DeepBuildVariant::Release.as_cmake_build_type(),
Some("Release")
);
assert_eq!(
DeepBuildVariant::RelWithDebInfo.as_cmake_build_type(),
Some("RelWithDebInfo")
);
assert_eq!(
DeepBuildVariant::MinSizeRel.as_cmake_build_type(),
Some("MinSizeRel")
);
assert_eq!(
DeepBuildVariant::PgoInstrumented.as_cmake_build_type(),
None
);
}
#[test]
fn test_detects_all_deep_project_ids() {
for id in DEEP_PROJECT_IDS {
assert!(
DeepProjectId::from_str(id).is_some(),
"Project ID '{}' should be recognized",
id
);
}
assert_eq!(DEEP_PROJECT_IDS.len(), 15);
}
#[test]
fn test_registry_creation() {
let registry = test_registry();
assert_eq!(registry.target_triple, X86_64_LINUX_TRIPLE);
assert_eq!(registry.target_cpu, "x86-64-v3");
assert!(registry.env.contains_key("CC"));
assert!(registry.env.contains_key("CXX"));
}
#[test]
fn test_register_and_retrieve_project() {
let mut registry = test_registry();
let config = llvm_deep_config();
registry.register(config);
let retrieved = registry.get_project(DeepProjectId::Llvm);
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().build_system, DeepBuildSystem::Cmake);
}
#[test]
fn test_register_all_projects() {
let mut registry = test_registry();
registry.register_default_projects();
assert_eq!(registry.projects.len(), 15);
}
#[test]
fn test_build_order_respects_dependencies() {
let mut registry = test_registry();
registry.register(abseil_deep_config());
registry.register(protobuf_deep_config());
registry.register(grpc_deep_config());
let order = registry.build_order();
let absl_pos = order
.iter()
.position(|&id| id == DeepProjectId::Abseil)
.unwrap();
let proto_pos = order
.iter()
.position(|&id| id == DeepProjectId::Protobuf)
.unwrap();
let grpc_pos = order
.iter()
.position(|&id| id == DeepProjectId::Grpc)
.unwrap();
assert!(
absl_pos < proto_pos,
"Abseil (pos {}) should come before Protobuf (pos {})",
absl_pos,
proto_pos
);
assert!(absl_pos < grpc_pos);
assert!(proto_pos < grpc_pos);
}
#[test]
fn test_validate_dependencies() {
let mut registry = test_registry();
registry.register(abseil_deep_config());
registry.register(protobuf_deep_config()); registry.register(grpc_deep_config());
let issues = registry.validate_dependencies();
assert!(
issues.is_empty(),
"Should have no dependency issues: {:?}",
issues
);
}
#[test]
fn test_validate_missing_dependency() {
let mut registry = test_registry();
registry.register(protobuf_deep_config());
let issues = registry.validate_dependencies();
assert!(
!issues.is_empty(),
"Should detect missing Abseil dependency"
);
}
#[test]
fn test_project_build_dir() {
let registry = test_registry();
let dir = registry.project_build_dir(DeepProjectId::Llvm, DeepBuildStage::Stage2);
assert!(dir.to_string_lossy().contains("llvm"));
assert!(dir.to_string_lossy().contains("stage2"));
}
#[test]
fn test_toolchain_file_generation() {
let registry = test_registry();
let content = registry.generate_toolchain_file();
assert!(content.contains("CMAKE_SYSTEM_NAME Linux"));
assert!(content.contains("CMAKE_C_COMPILER clang"));
assert!(content.contains("CMAKE_CXX_COMPILER clang++"));
assert!(content.contains("x86-64-v3"));
}
#[test]
fn test_init_subsystems() {
let mut registry = test_registry();
registry.init_subsystems();
assert!(registry.build.is_some());
assert!(registry.test.is_some());
assert!(registry.optimize.is_some());
}
#[test]
fn test_config_builder_pattern() {
let config = DeepProjectConfig::new(DeepProjectId::Llvm)
.with_variant(DeepBuildVariant::Release)
.with_lto()
.with_simd(DeepSimdLevel::Avx2)
.cmake_var("CMAKE_BUILD_TYPE", "Release")
.cflag("-march=x86-64-v3")
.cxxflag("-std=c++17")
.define("NDEBUG", None);
assert_eq!(config.variant, DeepBuildVariant::Release);
assert!(config.enable_lto);
assert_eq!(config.simd_level, DeepSimdLevel::Avx2);
assert_eq!(
config.cmake_vars.get("CMAKE_BUILD_TYPE").unwrap(),
"Release"
);
assert!(config.cflags.contains(&"-march=x86-64-v3".to_string()));
assert!(config.cxxflags.contains(&"-std=c++17".to_string()));
assert_eq!(config.defines[0], ("NDEBUG".to_string(), None));
}
#[test]
fn test_llvm_config() {
let config = llvm_deep_config();
assert_eq!(config.id, DeepProjectId::Llvm);
assert_eq!(config.build_system, DeepBuildSystem::Cmake);
assert!(config.cmake_vars.contains_key("LLVM_TARGETS_TO_BUILD"));
assert_eq!(
config.cmake_vars.get("LLVM_TARGETS_TO_BUILD").unwrap(),
"X86"
);
assert!(config.cmake_vars.contains_key("LLVM_ENABLE_PROJECTS"));
assert!(config
.cmake_vars
.get("LLVM_ENABLE_PROJECTS")
.unwrap()
.contains("clang"));
}
#[test]
fn test_llvm_bootstrap_config() {
let config = llvm_bootstrap_config();
assert!(config.supports_bootstrap);
assert_eq!(config.stage, DeepBuildStage::Stage1);
assert_eq!(
config.cmake_vars.get("CLANG_ENABLE_BOOTSTRAP").unwrap(),
"ON"
);
}
#[test]
fn test_linux_kernel_config() {
let config = linux_kernel_deep_config();
assert_eq!(config.id, DeepProjectId::LinuxKernel);
assert_eq!(config.build_system, DeepBuildSystem::Kbuild);
assert!(config.defines.iter().any(|(k, _)| k == "CONFIG_X86_64"));
assert!(config.cflags.iter().any(|f| f == "-mcmodel=kernel"));
assert!(config.cflags.iter().any(|f| f == "-mno-sse"));
}
#[test]
fn test_linux_kernel_i386_config() {
let config = linux_kernel_i386_config();
assert!(!config.defines.iter().any(|(k, _)| k == "CONFIG_X86_64"));
assert!(config.defines.iter().any(|(k, _)| k == "CONFIG_X86_32"));
assert!(config.cflags.iter().any(|f| f == "-m32"));
}
#[test]
fn test_qt_config() {
let config = qt_deep_config();
assert_eq!(config.id, DeepProjectId::Qt);
assert_eq!(config.build_system, DeepBuildSystem::Cmake);
assert_eq!(config.cmake_vars.get("QT_FEATURE_gui").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("QT_FEATURE_widgets").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("QT_ENABLE_AVX2").unwrap(), "ON");
assert!(config.test_config.is_some());
}
#[test]
fn test_boost_config() {
let config = boost_deep_config();
assert_eq!(config.id, DeepProjectId::Boost);
assert_eq!(config.build_system, DeepBuildSystem::BoostBuild);
let opts = &config.meson_options; assert!(opts.iter().any(|o| o.contains("--with-filesystem")));
assert!(opts.iter().any(|o| o.contains("--with-system")));
assert!(opts.iter().any(|o| o.contains("address-model=64")));
assert!(config.defines.iter().any(|(k, _)| k == "BOOST_USE_SSE2"));
}
#[test]
fn test_ffmpeg_config() {
let config = ffmpeg_deep_config();
assert_eq!(config.id, DeepProjectId::Ffmpeg);
assert_eq!(config.build_system, DeepBuildSystem::Autotools);
assert!(config
.configure_flags
.iter()
.any(|f| f.contains("--enable-avx512")));
assert!(config
.configure_flags
.iter()
.any(|f| f.contains("--enable-decoder=h264")));
assert!(config
.configure_flags
.iter()
.any(|f| f.contains("--enable-x86asm")));
}
#[test]
fn test_opencv_config() {
let config = opencv_deep_config();
assert_eq!(config.id, DeepProjectId::OpenCV);
assert_eq!(config.build_system, DeepBuildSystem::Cmake);
assert_eq!(config.cmake_vars.get("BUILD_opencv_core").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("CPU_BASELINE").unwrap(), "SSE4_2");
assert_eq!(
config.cmake_vars.get("CPU_DISPATCH").unwrap(),
"AVX;AVX2;AVX512_SKX"
);
}
#[test]
fn test_tensorflow_lite_config() {
let config = tensorflow_lite_deep_config();
assert_eq!(config.id, DeepProjectId::TensorFlowLite);
assert_eq!(
config.cmake_vars.get("TFLITE_ENABLE_XNNPACK").unwrap(),
"ON"
);
assert_eq!(config.cmake_vars.get("XNNPACK_ENABLE_AVX2").unwrap(), "ON");
assert!(config.dependencies.contains(&DeepProjectId::Abseil));
assert!(config.dependencies.contains(&DeepProjectId::Protobuf));
}
#[test]
fn test_protobuf_config() {
let config = protobuf_deep_config();
assert_eq!(config.id, DeepProjectId::Protobuf);
assert_eq!(
config
.cmake_vars
.get("protobuf_BUILD_PROTOC_BINARIES")
.unwrap(),
"ON"
);
assert!(config.dependencies.contains(&DeepProjectId::Abseil));
}
#[test]
fn test_grpc_config() {
let config = grpc_deep_config();
assert_eq!(config.id, DeepProjectId::Grpc);
assert_eq!(
config.cmake_vars.get("gRPC_SSL_PROVIDER").unwrap(),
"module"
);
assert!(config.dependencies.contains(&DeepProjectId::Abseil));
assert!(config.dependencies.contains(&DeepProjectId::Protobuf));
}
#[test]
fn test_abseil_config() {
let config = abseil_deep_config();
assert_eq!(config.id, DeepProjectId::Abseil);
assert_eq!(config.cmake_vars.get("CMAKE_CXX_STANDARD").unwrap(), "17");
assert!(config.dependencies.is_empty());
}
#[test]
fn test_leveldb_config() {
let config = leveldb_deep_config();
assert_eq!(config.id, DeepProjectId::LevelDb);
assert_eq!(config.cmake_vars.get("HAVE_SNAPPY").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("HAVE_CRC32C").unwrap(), "ON");
assert!(config.cflags.iter().any(|f| f == "-msse4.2"));
}
#[test]
fn test_rocksdb_config() {
let config = rocksdb_deep_config();
assert_eq!(config.id, DeepProjectId::RocksDb);
assert_eq!(config.cmake_vars.get("WITH_ZSTD").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("WITH_LZ4").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("PORTABLE").unwrap(), "OFF");
assert!(config
.test_config
.as_ref()
.unwrap()
.benchmark_config
.is_some());
}
#[test]
fn test_duckdb_config() {
let config = duckdb_deep_config();
assert_eq!(config.id, DeepProjectId::DuckDb);
assert_eq!(
config
.cmake_vars
.get("ENABLE_VECTORIZED_EXECUTION")
.unwrap(),
"ON"
);
assert_eq!(
config.cmake_vars.get("BUILD_PARQUET_EXTENSION").unwrap(),
"ON"
);
}
#[test]
fn test_clickhouse_config() {
let config = clickhouse_deep_config();
assert_eq!(config.id, DeepProjectId::ClickHouse);
assert_eq!(config.cmake_vars.get("CMAKE_CXX_STANDARD").unwrap(), "23");
assert_eq!(config.cmake_vars.get("ENABLE_AVX512").unwrap(), "ON");
assert_eq!(config.simd_level, DeepSimdLevel::Avx512Full);
}
#[test]
fn test_scylladb_config() {
let config = scylladb_deep_config();
assert_eq!(config.id, DeepProjectId::ScyllaDb);
assert_eq!(config.cmake_vars.get("Seastar_DPDK").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("Seastar_IO_URING").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("CMAKE_CXX_STANDARD").unwrap(), "20");
assert!(config.cxxflags.iter().any(|f| f == "-fcoroutines"));
}
#[test]
fn test_build_orchestrator_creation() {
let registry = test_registry();
let build = X86ProjectBuild::new(®istry);
assert!(build.incremental);
assert!(build.auto_patch);
assert!(!build.clean_build);
}
#[test]
fn test_resolve_build_order() {
let mut registry = test_registry();
registry.register(abseil_deep_config());
registry.register(protobuf_deep_config());
let mut build = X86ProjectBuild::new(®istry);
let order = build.resolve_build_order(®istry);
assert!(!order.is_empty());
assert_eq!(order[0], DeepProjectId::Abseil); }
#[test]
fn test_needs_rebuild_no_directory() {
let registry = test_registry();
let build = X86ProjectBuild::new(®istry);
let config = DeepProjectConfig::new(DeepProjectId::Llvm);
let dir = PathBuf::from("/nonexistent/build/dir");
assert!(build.needs_rebuild(&config, &dir));
}
#[test]
fn test_cancel_and_reset() {
let registry = test_registry();
let build = X86ProjectBuild::new(®istry);
assert!(!build.is_cancelled());
build.cancel_all();
assert!(build.is_cancelled());
build.reset_cancellation();
assert!(!build.is_cancelled());
}
#[test]
fn test_cache_creation() {
let tmp = env::temp_dir().join("llvm-native-test-cache");
let cache = DeepBuildCache::new(&tmp);
assert!(cache.enabled);
assert_eq!(cache.current_size, 0);
assert!(cache.hit_rate() >= 0.0);
}
#[test]
fn test_cache_key_computation() {
let key1 = DeepBuildCache::compute_key("int main() {}", &["-O2".to_string()]);
let key2 = DeepBuildCache::compute_key("int main() {}", &["-O2".to_string()]);
let key3 = DeepBuildCache::compute_key("int main() {}", &["-O3".to_string()]);
assert_eq!(key1, key2);
assert_ne!(key1, key3);
}
#[test]
fn test_cache_stats() {
let tmp = env::temp_dir().join("llvm-native-test-cache-stats");
let cache = DeepBuildCache::new(&tmp);
let stats = cache.stats();
assert!(stats.contains("Cache:"));
assert!(stats.contains("hit rate"));
}
#[test]
fn test_test_system_creation() {
let registry = test_registry();
let test_sys = X86ProjectTest::new(®istry);
assert_eq!(test_sys.default_timeout_secs, TEST_TIMEOUT_SECS);
assert!(test_sys.rerun_failed);
assert_eq!(test_sys.rerun_attempts, 3);
}
#[test]
fn test_empty_test_report() {
let report = DeepTestReport::new(DeepProjectId::Llvm);
assert!(!report.all_passed);
assert_eq!(report.total, 0);
assert_eq!(report.pass_rate(), 1.0);
}
#[test]
fn test_test_report_with_results() {
let mut report = DeepTestReport::new(DeepProjectId::Llvm);
report.total = 10;
report.passed = 8;
report.failed = 2;
assert!(!report.all_passed);
assert!((report.pass_rate() - 0.8).abs() < 0.001);
assert!(report.summary().contains("8/10"));
}
#[test]
fn test_optimize_creation() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
assert!(!opt.keep_intermediates);
assert!(!opt.verbose);
}
#[test]
fn test_pgo_instrumented_flags() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
let flags = opt.generate_pgo_instrumented_flags();
assert!(flags.iter().any(|f| f.contains("fprofile-generate")));
}
#[test]
fn test_pgo_use_flags() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
let flags = opt.generate_pgo_use_flags(Path::new("/tmp/profiles"));
assert!(flags.iter().any(|f| f.contains("fprofile-use")));
}
#[test]
fn test_thin_lto_cmake_flags() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
let flags = opt.generate_thin_lto_cmake_flags();
assert_eq!(flags.get("LLVM_ENABLE_LTO").unwrap(), "Thin");
assert!(flags.get("CMAKE_C_FLAGS").unwrap().contains("flto=thin"));
}
#[test]
fn test_full_lto_cmake_flags() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
let flags = opt.generate_full_lto_cmake_flags();
assert_eq!(flags.get("LLVM_ENABLE_LTO").unwrap(), "Full");
assert!(flags.get("CMAKE_C_FLAGS").unwrap().contains("flto=full"));
}
#[test]
fn test_fmv_attribute_generation() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
let targets = vec!["x86-64".to_string(), "x86-64-v3".to_string()];
let attr = opt.generate_fmv_attributes(&targets);
assert!(attr.contains("target_clones"));
assert!(attr.contains("default"));
assert!(attr.contains("avx2"));
}
#[test]
fn test_fmv_sanitize_target() {
let registry = test_registry();
let opt = X86ProjectOptimize::new(®istry);
assert_eq!(opt.sanitize_fmv_target("x86-64"), "default");
assert_eq!(opt.sanitize_fmv_target("x86-64-v2"), "sse4.2,popcnt");
assert_eq!(
opt.sanitize_fmv_target("x86-64-v3"),
"avx2,bmi,bmi2,fma,lzcnt"
);
assert_eq!(
opt.sanitize_fmv_target("x86-64-v4"),
"avx512f,avx512bw,avx512dq,avx512vl"
);
assert_eq!(opt.sanitize_fmv_target("haswell"), "avx2");
assert_eq!(opt.sanitize_fmv_target("unknown"), "unknown");
}
#[test]
fn test_lto_config_default() {
let lto = DeepLtoConfig::default();
assert!(!lto.enabled);
assert_eq!(lto.mode, "thin");
assert!(lto.use_new_pm);
}
#[test]
fn test_lto_compiler_flags_disabled() {
let lto = DeepLtoConfig::default();
assert!(lto.compiler_flags().is_empty());
}
#[test]
fn test_lto_compiler_flags_enabled() {
let mut lto = DeepLtoConfig::default();
lto.enabled = true;
let flags = lto.compiler_flags();
assert!(flags.iter().any(|f| f.contains("flto=thin")));
}
#[test]
fn test_patch_inline_creation() {
let patch = DeepPatch::new_inline(
"Fix missing include",
"src/main.c",
"#include <old.h>",
"#include <new.h>",
);
assert_eq!(patch.target_file, "src/main.c");
assert!(patch.required);
assert!(!patch.is_diff_file);
}
#[test]
fn test_patch_diff_creation() {
let patch =
DeepPatch::new_diff("Backport fix", "src/config.h", Path::new("/tmp/fix.patch"));
assert!(patch.is_diff_file);
assert!(patch.patch_file_path.is_some());
}
#[test]
fn test_build_report_creation() {
let report = DeepBuildReport::new(DeepProjectId::Llvm);
assert_eq!(report.status, DeepBuildStatus::Pending);
assert_eq!(report.tus_compiled, 0);
assert!(report.elapsed().is_zero());
assert!(!report.is_success());
}
#[test]
fn test_build_report_summary() {
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
report.status = DeepBuildStatus::Success;
report.tus_compiled = 5000;
report.warning_count = 12;
let summary = report.summary();
assert!(summary.contains("LLVM/Clang"));
assert!(summary.contains("success"));
}
#[test]
fn test_build_event_types() {
let types = [
DeepBuildEventType::BuildStarted,
DeepBuildEventType::BuildCompleted,
DeepBuildEventType::BuildFailed,
DeepBuildEventType::ConfigureStarted,
DeepBuildEventType::CompileStarted,
];
for t in &types {
assert!(!t.as_str().is_empty());
}
}
#[test]
fn test_event_logging() {
let mut log = Vec::new();
log_event(
&mut log,
DeepBuildEvent {
project_id: DeepProjectId::Llvm,
event_type: DeepBuildEventType::BuildStarted,
message: "Starting LLVM build".to_string(),
timestamp: SystemTime::now(),
duration: None,
},
);
assert_eq!(log.len(), 1);
assert_eq!(log[0].project_id, DeepProjectId::Llvm);
}
#[test]
fn test_sanitizer_flags() {
assert_eq!(DeepSanitizer::Address.to_cflag(), "-fsanitize=address");
assert_eq!(DeepSanitizer::Thread.to_cflag(), "-fsanitize=thread");
assert_eq!(DeepSanitizer::Undefined.to_cflag(), "-fsanitize=undefined");
assert_eq!(
DeepSanitizer::AddressUndefined.to_cflag(),
"-fsanitize=address,undefined"
);
}
#[test]
fn test_simd_level_to_march() {
assert_eq!(DeepSimdLevel::Sse2.to_march_flag(), Some("pentium4"));
assert_eq!(DeepSimdLevel::Avx2.to_march_flag(), Some("haswell"));
assert_eq!(
DeepSimdLevel::Avx512F.to_march_flag(),
Some("skylake-avx512")
);
assert_eq!(DeepSimdLevel::None.to_march_flag(), None);
}
#[test]
fn test_simd_level_to_gcc_target_flag() {
assert_eq!(DeepSimdLevel::Sse2.to_gcc_target_flag(), None);
assert_eq!(DeepSimdLevel::Avx2.to_gcc_target_flag(), Some("avx2"));
assert_eq!(
DeepSimdLevel::Avx512Full.to_gcc_target_flag(),
Some("avx512f,avx512bw,avx512dq,avx512vl,avx512cd")
);
}
#[test]
fn test_build_status_terminal() {
assert!(DeepBuildStatus::Success.is_terminal());
assert!(DeepBuildStatus::Failed.is_terminal());
assert!(DeepBuildStatus::Cancelled.is_terminal());
assert!(!DeepBuildStatus::Pending.is_terminal());
assert!(!DeepBuildStatus::Building.is_terminal());
}
#[test]
fn test_build_status_running() {
assert!(DeepBuildStatus::Configuring.is_running());
assert!(DeepBuildStatus::Building.is_running());
assert!(!DeepBuildStatus::Pending.is_running());
assert!(!DeepBuildStatus::Success.is_running());
}
#[test]
fn test_opt_report_summary() {
let mut report = DeepOptimizationReport::new(DeepProjectId::Llvm);
report.pgo_applied = true;
report.pgo_speedup_pct = Some(15.0);
report.lto_applied = true;
report.lto_size_reduction_pct = Some(10.0);
let summary = report.summary();
assert!(summary.contains("LLVM/Clang"));
assert!(summary.contains("PGO"));
assert!(summary.contains("LTO"));
}
#[test]
fn test_build_summary_empty() {
let summary = build_summary(&[]);
assert!(summary.contains("0 total"));
}
#[test]
fn test_build_summary_with_results() {
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
report.status = DeepBuildStatus::Success;
report.tus_compiled = 100;
let summary = build_summary(&[report]);
assert!(summary.contains("1 total"));
assert!(summary.contains("1 succeeded"));
}
#[test]
fn test_test_summary() {
let mut results = BTreeMap::new();
let mut report = DeepTestReport::new(DeepProjectId::Llvm);
report.total = 100;
report.passed = 95;
report.failed = 3;
report.skipped = 2;
results.insert(DeepProjectId::Llvm, report);
let summary = test_summary(&results);
assert!(summary.contains("Projects tested: 1"));
assert!(summary.contains("95 passed"));
}
#[test]
fn test_cmake_presets_generation() {
let mut registry = test_registry();
registry.register(llvm_deep_config());
let presets = generate_cmake_presets(®istry);
assert!(presets.contains("\"version\": 6"));
assert!(presets.contains("llvm-release"));
}
#[test]
fn test_default_release_opt_config() {
let config = default_release_opt_config();
assert!(config.enable_thin_lto);
assert!(config.enable_fmv);
}
#[test]
fn test_aggressive_opt_config() {
let config = aggressive_opt_config();
assert!(config.enable_pgo);
assert!(config.enable_thin_lto);
assert!(config.enable_bolt);
assert!(config.enable_fmv);
assert!(config.use_cs_pgo);
}
#[test]
fn test_full_registry_workflow() {
let mut registry = test_registry();
registry.register_default_projects();
registry.init_subsystems();
assert_eq!(registry.projects.len(), 15);
let ids: Vec<_> = registry.projects.keys().collect();
let unique: HashSet<_> = ids.iter().copied().collect();
assert_eq!(ids.len(), unique.len());
let order = registry.build_order();
assert!(!order.is_empty());
for id in registry.projects.keys() {
assert!(
order.contains(id),
"Project {} should be in build order",
id.display_name()
);
}
}
#[test]
fn test_dependency_chain() {
let mut registry = test_registry();
registry.register(abseil_deep_config());
registry.register(protobuf_deep_config());
registry.register(grpc_deep_config());
registry.register(tensorflow_lite_deep_config());
let order = registry.build_order();
let absl_pos = order
.iter()
.position(|&id| id == DeepProjectId::Abseil)
.unwrap();
let proto_pos = order
.iter()
.position(|&id| id == DeepProjectId::Protobuf)
.unwrap();
let grpc_pos = order
.iter()
.position(|&id| id == DeepProjectId::Grpc)
.unwrap();
let tflite_pos = order
.iter()
.position(|&id| id == DeepProjectId::TensorFlowLite)
.unwrap();
assert!(absl_pos < proto_pos);
assert!(absl_pos < grpc_pos);
assert!(proto_pos < grpc_pos);
assert!(absl_pos < tflite_pos);
assert!(proto_pos < tflite_pos);
}
#[test]
fn test_all_project_factories_produce_valid_configs() {
let factories: Vec<fn() -> DeepProjectConfig> = vec![
llvm_deep_config,
linux_kernel_deep_config,
qt_deep_config,
boost_deep_config,
ffmpeg_deep_config,
opencv_deep_config,
tensorflow_lite_deep_config,
protobuf_deep_config,
grpc_deep_config,
abseil_deep_config,
leveldb_deep_config,
rocksdb_deep_config,
duckdb_deep_config,
clickhouse_deep_config,
scylladb_deep_config,
];
let mut seen_ids = HashSet::new();
for factory in factories {
let config = factory();
assert!(
!config.name.is_empty(),
"Config from factory should have a name"
);
assert!(!config.version.is_empty(), "Config should have a version");
assert!(
!seen_ids.contains(&config.id),
"Duplicate project ID: {:?}",
config.id
);
seen_ids.insert(config.id);
}
assert_eq!(seen_ids.len(), 15);
}
#[test]
fn test_simd_level_ordering() {
assert!(DeepSimdLevel::Avx2 > DeepSimdLevel::Avx);
assert!(DeepSimdLevel::Avx512Full > DeepSimdLevel::Avx512F);
assert!(DeepSimdLevel::Sse42 > DeepSimdLevel::Sse2);
assert!(DeepSimdLevel::Avx > DeepSimdLevel::Sse42);
}
#[test]
fn test_deep_build_stage_ordering() {
assert!(DeepBuildStage::Stage3 > DeepBuildStage::Stage2);
assert!(DeepBuildStage::Stage2 > DeepBuildStage::Stage1);
assert!(DeepBuildStage::Stage1 > DeepBuildStage::Stage0);
}
#[test]
fn test_x86_cross_target_x86_64_linux() {
let target = X86CrossTarget::x86_64_linux_gnu();
assert_eq!(target.triple, X86_64_LINUX_TRIPLE);
assert!(!target.is_32bit);
assert_eq!(target.data_model, X86DataModel::Lp64);
assert_eq!(target.stack_alignment, 16);
assert_eq!(target.red_zone_size, 128);
}
#[test]
fn test_x86_cross_target_i686() {
let target = X86CrossTarget::i686_linux_gnu();
assert_eq!(target.triple, X86_32_LINUX_TRIPLE);
assert!(target.is_32bit);
assert_eq!(target.data_model, X86DataModel::Ilp32);
assert_eq!(target.red_zone_size, 0);
}
#[test]
fn test_x86_cross_target_windows() {
let target = X86CrossTarget::x86_64_windows_msvc();
assert_eq!(target.os, X86TargetOs::Windows);
assert_eq!(target.data_model, X86DataModel::Llp64);
assert!(!target.default_pic);
}
#[test]
fn test_cross_target_cmake_toolchain() {
let target = X86CrossTarget::x86_64_linux_gnu();
let tc = target.to_cmake_toolchain();
assert!(tc.contains("CMAKE_SYSTEM_NAME Linux"));
assert!(tc.contains("x86_64-unknown-linux-gnu"));
}
#[test]
fn test_data_model_sizes() {
assert_eq!(X86DataModel::Lp64.sizeof_long(), 8);
assert_eq!(X86DataModel::Lp64.sizeof_pointer(), 8);
assert_eq!(X86DataModel::Ilp32.sizeof_long(), 4);
assert_eq!(X86DataModel::Ilp32.sizeof_pointer(), 4);
assert_eq!(X86DataModel::Llp64.sizeof_long(), 4);
assert_eq!(X86DataModel::Llp64.sizeof_pointer(), 8);
}
#[test]
fn test_container_build_config_default() {
let cfg = ContainerBuildConfig::default();
assert_eq!(cfg.base_image, "ubuntu:24.04");
assert!(cfg.use_buildkit);
assert!(cfg.rm);
assert!(!cfg.packages.is_empty());
}
#[test]
fn test_container_runtime_commands() {
assert_eq!(ContainerRuntime::Docker.command(), "docker");
assert_eq!(ContainerRuntime::Podman.command(), "podman");
assert_eq!(ContainerRuntime::Singularity.command(), "singularity");
}
#[test]
fn test_dockerfile_generation() {
let config = llvm_deep_config();
let container_cfg = ContainerBuildConfig::default();
let dockerfile = generate_project_dockerfile(&config, &container_cfg);
assert!(dockerfile.contains("FROM ubuntu:24.04"));
assert!(dockerfile.contains("clang"));
assert!(dockerfile.contains("cmake"));
}
#[test]
fn test_build_matrix_generation() {
let matrix = generate_build_matrix(&[DeepProjectId::Llvm]);
assert!(!matrix.is_empty());
for entry in &matrix {
if entry.variant == DeepBuildVariant::Debug {
assert!(!entry.lto, "Debug builds should not have LTO");
}
}
}
#[test]
fn test_build_matrix_entry_key() {
let entry = BuildMatrixEntry {
project_id: DeepProjectId::Llvm,
variant: DeepBuildVariant::Release,
simd_level: DeepSimdLevel::Avx2,
target: X86_64_LINUX_TRIPLE.to_string(),
microarch: "haswell".to_string(),
lto: true,
sanitizer: None,
labels: vec![],
};
let key = entry.key();
assert!(key.contains("llvm"));
assert!(key.contains("release"));
assert!(key.contains("lto"));
}
#[test]
fn test_patch_set_creation() {
let set = PatchSet::new(DeepProjectId::Llvm);
assert!(set.auto_apply);
assert_eq!(set.total_patches(), 0);
}
#[test]
fn test_patch_set_add_and_count() {
let mut set = PatchSet::new(DeepProjectId::Llvm);
set.add(
"build-fix",
DeepPatch::new_inline("test", "file.c", "old", "new"),
);
set.add(
"build-fix",
DeepPatch::new_inline("test2", "file2.c", "old", "new"),
);
assert_eq!(set.total_patches(), 2);
assert_eq!(set.required_patches().len(), 2);
}
#[test]
fn test_common_clang_compat_patches() {
let set = common_clang_compat_patches(DeepProjectId::Llvm);
assert!(set.total_patches() > 0);
}
#[test]
fn test_ci_pipeline_default() {
let pipeline = CIPipelineConfig::default();
assert!(!pipeline.nightly);
assert!(pipeline.include_sanitizers);
assert!(!pipeline.projects.is_empty());
}
#[test]
fn test_github_actions_workflow() {
let pipeline = CIPipelineConfig::default();
let yaml = generate_github_actions_workflow(&pipeline);
assert!(yaml.contains("on:"));
assert!(yaml.contains("runs-on"));
assert!(yaml.contains("steps:"));
}
#[test]
fn test_gitlab_ci_yaml() {
let mut pipeline = CIPipelineConfig::default();
pipeline.projects = vec![DeepProjectId::Llvm];
let yaml = generate_gitlab_ci_yaml(&pipeline);
assert!(yaml.contains("stages:"));
assert!(yaml.contains("build-llvm"));
}
#[test]
fn test_build_history_recording() {
let mut history = BuildHistory::new(DeepProjectId::Llvm);
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
report.status = DeepBuildStatus::Success;
report.tus_compiled = 500;
report.warning_count = 3;
history.record(&report);
history.record(&report);
assert_eq!(history.records.len(), 2);
}
#[test]
fn test_build_history_trends() {
let mut history = BuildHistory::new(DeepProjectId::Llvm);
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
report.status = DeepBuildStatus::Success;
for _ in 0..5 {
history.record(&report);
}
let summary = history.trend_summary();
assert!(summary.contains("Build Trends"));
}
#[test]
fn test_diff_builds_no_change() {
let prev = DeepBuildReport::new(DeepProjectId::Llvm);
let curr = DeepBuildReport::new(DeepProjectId::Llvm);
let diff = diff_builds(&prev, &curr);
assert_eq!(diff.impact, DiffImpact::NoChange);
assert_eq!(diff.size_delta_bytes, 0);
}
#[test]
fn test_diff_builds_error() {
let mut prev = DeepBuildReport::new(DeepProjectId::Llvm);
prev.status = DeepBuildStatus::Success;
let mut curr = DeepBuildReport::new(DeepProjectId::Llvm);
curr.status = DeepBuildStatus::Failed;
curr.error_count = 5;
let diff = diff_builds(&prev, &curr);
assert_eq!(diff.impact, DiffImpact::Breaking);
}
#[test]
fn test_diff_impact_display() {
assert_eq!(DiffImpact::NoChange.emoji(), "⚪");
assert_eq!(DiffImpact::Minor.emoji(), "🟢");
assert_eq!(DiffImpact::Breaking.emoji(), "🔴");
}
#[test]
fn test_glob_match_simple() {
assert!(glob_match("*.c", "main.c"));
assert!(glob_match("*.cpp", "foo.cpp"));
assert!(!glob_match("*.c", "main.h"));
assert!(glob_match("src/*.c", "src/main.c"));
assert!(!glob_match("src/*.c", "test/main.c"));
}
#[test]
fn test_glob_match_wildcard() {
assert!(glob_match("**/*.rs", "src/main.rs"));
assert!(glob_match("**/*.rs", "src/clang/test.rs"));
assert!(!glob_match("**/*.rs", "src/main.c"));
}
#[test]
fn test_scons_support() {
let scons = X86SconsSupport::new(Path::new("/tmp"));
assert!(scons.build_command().contains("scons"));
assert_eq!(scons.target_platform, "posix");
}
#[test]
fn test_premake_support() {
let premake = X86PremakeSupport::new(Path::new("/tmp"));
let cmd = premake.generate_command();
assert!(cmd.contains("premake5"));
assert!(cmd.contains("linux"));
assert!(cmd.contains("x86_64"));
}
#[test]
fn test_premake_windows_cross() {
let premake = X86PremakeSupport::windows_cross();
assert_eq!(premake.action, "vs2022");
assert_eq!(premake.os, "windows");
}
#[test]
fn test_feature_matrix_contains_avx2() {
let matrix = x86_compiler_feature_matrix();
let avx2_entry = matrix.iter().find(|e| e.flag == "-mavx2");
assert!(avx2_entry.is_some());
let entry = avx2_entry.unwrap();
assert!(entry.clang_support);
assert!(entry.gcc_support);
}
#[test]
fn test_feature_matrix_thin_lto() {
let matrix = x86_compiler_feature_matrix();
let thin_lto = matrix.iter().find(|e| e.flag == "-flto=thin");
assert!(thin_lto.is_some());
assert!(!thin_lto.unwrap().gcc_support, "ThinLTO is Clang-only");
}
#[test]
fn test_feature_matrix_size() {
let matrix = x86_compiler_feature_matrix();
assert_eq!(matrix.len(), 10);
}
#[test]
fn test_isolated_env_none() {
let env = IsolatedBuildEnv {
isolation_type: IsolationType::None,
root_path: None,
packages: vec![],
pass_env: vec![],
work_dir: PathBuf::from("/tmp"),
use_overlay: false,
};
assert!(env.command_prefix().is_empty());
}
#[test]
fn test_isolated_env_chroot() {
let env = IsolatedBuildEnv {
isolation_type: IsolationType::Chroot,
root_path: Some(PathBuf::from("/chroot")),
packages: vec![],
pass_env: vec![],
work_dir: PathBuf::from("/tmp"),
use_overlay: false,
};
let prefix = env.command_prefix();
assert!(prefix.contains(&"chroot".to_string()));
assert!(prefix.contains(&"/chroot".to_string()));
}
#[test]
fn test_llvm_minimal_config() {
let config = llvm_minimal_config();
assert_eq!(config.cmake_vars.get("LLVM_BUILD_TOOLS").unwrap(), "OFF");
assert_eq!(config.cmake_vars.get("LLVM_BUILD_TESTS").unwrap(), "OFF");
}
#[test]
fn test_llvm_fuzz_config() {
let config = llvm_fuzz_config();
assert_eq!(config.variant, DeepBuildVariant::Fuzz);
assert!(config.cflags.iter().any(|f| f.contains("fuzzer")));
}
#[test]
fn test_qt_core_only_config() {
let config = qt_core_only_config();
assert_eq!(config.cmake_vars.get("QT_FEATURE_gui").unwrap(), "OFF");
assert_eq!(config.cmake_vars.get("QT_FEATURE_widgets").unwrap(), "OFF");
}
#[test]
fn test_ffmpeg_minimal_config() {
let config = ffmpeg_minimal_config();
assert!(config
.configure_flags
.iter()
.any(|f| f.contains("--disable-decoders")));
assert!(config
.configure_flags
.iter()
.any(|f| f.contains("--enable-decoder=h264")));
}
#[test]
fn test_opencv_cuda_config() {
let config = opencv_cuda_config();
assert_eq!(config.cmake_vars.get("WITH_CUDA").unwrap(), "ON");
assert_eq!(config.cmake_vars.get("OPENCV_DNN_CUDA").unwrap(), "ON");
}
#[test]
fn test_simd_dispatch_code_generation() {
let entries = vec![SimdDispatchEntry {
function_name: "process_block".to_string(),
base_isa: DeepSimdLevel::Sse2,
variants: vec![
SimdVariant {
isa_level: DeepSimdLevel::Avx2,
suffix: "_avx2".to_string(),
required_features: vec!["avx2".to_string()],
},
SimdVariant {
isa_level: DeepSimdLevel::Avx512F,
suffix: "_avx512".to_string(),
required_features: vec!["avx512f".to_string()],
},
],
resolver: "resolve_process_block".to_string(),
}];
let code = generate_simd_dispatch_code(&entries);
assert!(code.contains("process_block"));
assert!(code.contains("cpuid.h"));
assert!(code.contains("cpu_has_feature"));
}
#[test]
fn test_notifier_format_message() {
let notifier = BuildNotifier::default();
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
report.tus_compiled = 100;
report.warning_count = 2;
report.error_count = 0;
let msg = notifier.format_message(¬ifier.templates.success, &report);
assert!(msg.contains("LLVM/Clang"));
assert!(msg.contains("succeeded"));
}
#[test]
fn test_platform_info_detection() {
let info = X86PlatformInfo::detect();
assert!(!info.cpu_model.is_empty());
assert!(info.cpu_cores > 0);
assert!(info.cpu_threads > 0);
assert!(info.total_memory_mb > 0);
assert!(!info.cpu_features.is_empty());
}
#[test]
fn test_platform_info_summary() {
let info = X86PlatformInfo::detect();
let summary = info.summary();
assert!(summary.contains("cores"));
assert!(summary.contains("RAM"));
}
#[test]
fn test_build_profiler() {
let mut profiler = BuildProfiler::new(DeepProjectId::Llvm);
profiler.add_result(&["-O2".to_string()], 120.0, 50_000_000, 1000);
profiler.add_result(&["-O3".to_string()], 180.0, 55_000_000, 950);
profiler.add_result(&["-Os".to_string()], 90.0, 30_000_000, 1200);
let best = profiler.evaluate();
assert!(best.is_some());
assert!(!profiler.configurations.is_empty());
let report = profiler.report();
assert!(report.contains("Build Profiling Report"));
}
#[test]
fn test_build_profiler_report_contains_best() {
let mut profiler = BuildProfiler::new(DeepProjectId::Llvm);
profiler.add_result(&["-O2".to_string()], 100.0, 40_000_000, 1000);
profiler.evaluate();
let report = profiler.report();
assert!(report.contains("Best configuration"));
}
#[test]
fn test_toolchain_database_size() {
let db = x86_toolchain_database();
assert!(db.len() >= 8);
}
#[test]
fn test_find_toolchain_by_triple() {
let toolchain = find_toolchain("x86_64-unknown-linux-gnu");
assert!(toolchain.is_some());
assert_eq!(toolchain.unwrap().data_model, X86DataModel::Lp64);
}
#[test]
fn test_find_toolchain_musl() {
let toolchain = find_toolchain("x86_64-unknown-linux-musl");
assert!(toolchain.is_some());
assert!(toolchain
.unwrap()
.default_ldflags
.contains(&"-static".to_string()));
}
#[test]
fn test_known_triples() {
let triples = known_triples();
assert!(triples.contains(&"x86_64-unknown-linux-gnu".to_string()));
assert!(triples.contains(&"i686-unknown-linux-gnu".to_string()));
}
#[test]
fn test_health_check_runs() {
let result = check_build_environment();
assert!(!result.checks.is_empty());
let report = result.print_report();
assert!(report.contains("Build Environment Health Check"));
}
#[test]
fn test_health_check_items_have_names() {
let result = check_build_environment();
for check in &result.checks {
assert!(!check.name.is_empty());
}
}
#[test]
fn test_diagnostic_comparison() {
let clang_out = "file.c:10:5: warning: unused variable
file.c:20:1: error: expected ';'";
let gcc_out = "file.c:10:5: warning: unused variable";
let comparison = compare_diagnostics(clang_out, gcc_out);
assert_eq!(comparison.clang_errors, 1);
assert_eq!(comparison.clang_warnings, 1);
assert_eq!(comparison.gcc_errors, 0);
assert_eq!(comparison.gcc_warnings, 1);
}
#[test]
fn test_diagnostic_comparison_summary() {
let comparison = compare_diagnostics("error: x", "warning: y");
let summary = comparison.summary();
assert!(summary.contains("Clang"));
assert!(summary.contains("GCC"));
}
#[test]
fn test_export_build_report_json() {
let report = DeepBuildReport::new(DeepProjectId::Llvm);
let json = export_build_report(&report, "json");
assert!(json.contains(""project""));
assert!(json.contains(""status""));
}
#[test]
fn test_export_build_report_markdown() {
let report = DeepBuildReport::new(DeepProjectId::Llvm);
let md = export_build_report(&report, "markdown");
assert!(md.contains("# Build Report"));
assert!(md.contains("LLVM/Clang"));
}
#[test]
fn test_export_test_report_junit() {
let mut report = DeepTestReport::new(DeepProjectId::Llvm);
report.total = 1;
report.passed = 1;
report.cases.push(DeepTestCase {
suite: "TestSuite".to_string(),
name: "test_foo".to_string(),
passed: true,
duration: Duration::from_millis(100),
failure_message: None,
output: String::new(),
tags: vec![],
is_flaky: false,
skipped: false,
});
let xml = export_test_report(&report, "junit");
assert!(xml.contains("testsuite"));
assert!(xml.contains("testcase"));
}
#[test]
fn test_scan_empty_directory() {
let tmp = env::temp_dir().join("llvm-native-scan-empty");
let _ = fs::create_dir_all(&tmp);
let result = scan_for_projects(&tmp).unwrap();
assert!(result.detected_projects.is_empty());
assert!(result.directories_scanned > 0);
let _ = fs::remove_dir_all(&tmp);
}
#[test]
fn test_build_script_cmake() {
let registry = test_registry();
let config = llvm_deep_config();
let script = generate_build_script(&config, ®istry);
assert!(script.contains("#!/usr/bin/env bash"));
assert!(script.contains("cmake -G Ninja"));
assert!(script.contains("export CC=clang"));
assert!(script.contains("set -euo pipefail"));
}
#[test]
fn test_build_script_autotools() {
let registry = test_registry();
let config = ffmpeg_deep_config();
let script = generate_build_script(&config, ®istry);
assert!(script.contains("./configure"));
assert!(script.contains("--enable-gpl"));
}
#[test]
fn test_build_schedule_creation() {
let schedule = BuildSchedule::new("nightly");
assert_eq!(schedule.name, "nightly");
assert!(schedule.enabled);
assert!(!schedule.is_due());
assert!(schedule.projects.is_empty());
}
#[test]
fn test_build_scheduler_add() {
let mut scheduler = BuildScheduler::new();
scheduler.add(BuildSchedule::new("test-schedule"));
assert_eq!(scheduler.schedules.len(), 1);
assert!(scheduler.due_schedules().is_empty());
}
#[test]
fn test_scheduler_list() {
let mut scheduler = BuildScheduler::new();
let mut schedule = BuildSchedule::new("nightly");
schedule.projects = vec![DeepProjectId::Llvm];
schedule.cron_expr = Some("0 2 * * *".to_string());
scheduler.add(schedule);
let list = scheduler.list_schedules();
assert!(list.contains("nightly"));
assert!(list.contains("llvm"));
}
#[test]
fn test_build_metrics_throughput() {
let metrics = BuildMetrics {
project_id: DeepProjectId::Llvm,
wall_time_secs: 100.0,
cpu_time_secs: 400.0,
user_time_secs: 350.0,
system_time_secs: 50.0,
max_rss_mb: 4096.0,
page_faults: 10000,
context_switches: 50000,
io_read_bytes: 100_000_000,
io_write_bytes: 200_000_000,
compile_units: 5000,
link_units: 100,
cache_hits: 4500,
cache_misses: 500,
success: true,
};
assert!(metrics.throughput_tus_per_sec() > 0.0);
assert!(metrics.cache_hit_rate() > 0.8);
assert!(metrics.format_summary().contains("Build Metrics"));
}
#[test]
fn test_build_metrics_zero_time() {
let metrics = BuildMetrics {
wall_time_secs: 0.0,
cpu_time_secs: 0.0,
user_time_secs: 0.0,
system_time_secs: 0.0,
max_rss_mb: 0.0,
page_faults: 0,
context_switches: 0,
io_read_bytes: 0,
io_write_bytes: 0,
compile_units: 0,
link_units: 0,
cache_hits: 0,
cache_misses: 0,
success: false,
project_id: DeepProjectId::Llvm,
};
assert_eq!(metrics.throughput_tus_per_sec(), 0.0);
assert_eq!(metrics.cache_hit_rate(), 0.0);
}
#[test]
fn test_warning_baseline_new() {
let baseline = WarningBaseline::new(DeepProjectId::Llvm);
assert_eq!(baseline.warning_count, 0);
assert!(baseline.warning_hashes.is_empty());
}
#[test]
fn test_warning_hash_stability() {
let hash1 = WarningBaseline::hash_warning("unused variable 'x'", "file.c", 10);
let hash2 = WarningBaseline::hash_warning("unused variable 'x'", "file.c", 10);
assert_eq!(hash1, hash2);
let hash3 = WarningBaseline::hash_warning("unused variable 'x'", "file.c", 11);
assert_ne!(hash1, hash3);
}
#[test]
fn test_warning_baseline_add() {
let mut baseline = WarningBaseline::new(DeepProjectId::Llvm);
let hash = WarningBaseline::hash_warning("unused variable", "file.c", 5);
baseline.add_warning(hash.clone());
assert_eq!(baseline.warning_count, 1);
assert!(baseline.is_known(&hash));
}
#[test]
fn test_neon_to_sse_mapping() {
let map = neon_to_sse_mapping_table();
assert!(map.len() >= 20);
assert_eq!(map.get("vaddq_f32").unwrap(), "_mm_add_ps");
assert_eq!(map.get("vmulq_f32").unwrap(), "_mm_mul_ps");
}
#[test]
fn test_translate_neon_to_sse_simple() {
let neon_code = "float32x4_t a = vaddq_f32(x, y);";
let sse_code = translate_neon_to_sse(neon_code);
assert!(sse_code.contains("_mm_add_ps"));
assert!(!sse_code.contains("vaddq_f32"));
}
#[test]
fn test_translate_neon_adds_header() {
let neon_code = "float32x4_t a = _mm_add_ps(x, y);";
let result = translate_neon_to_sse(neon_code);
assert!(result.contains("#include <xmmintrin.h>"));
}
#[test]
fn test_static_analysis_config_default() {
let cfg = StaticAnalysisConfig::default();
assert!(cfg.run_clang_tidy);
assert!(!cfg.run_iwyu);
assert!(cfg.warnings_as_errors);
assert!(!cfg.tidy_checks.is_empty());
}
#[test]
fn test_extended_benchmark_config_default() {
let cfg = ExtendedBenchmarkConfig::default();
assert!(cfg.warmup);
assert_eq!(cfg.iterations, 10);
assert!(cfg.compare_baseline);
assert_eq!(cfg.max_regression_pct, 5.0);
}
#[test]
fn test_bench_output_formats() {
assert_eq!(BenchOutputFormat::Json as u8, BenchOutputFormat::Json as u8);
assert_ne!(BenchOutputFormat::Json as u8, BenchOutputFormat::Csv as u8);
}
#[test]
fn test_all_project_ids_have_display_names() {
for id in &[
DeepProjectId::Llvm,
DeepProjectId::LinuxKernel,
DeepProjectId::Qt,
DeepProjectId::Boost,
DeepProjectId::Ffmpeg,
DeepProjectId::OpenCV,
DeepProjectId::TensorFlowLite,
DeepProjectId::Protobuf,
DeepProjectId::Grpc,
DeepProjectId::Abseil,
DeepProjectId::LevelDb,
DeepProjectId::RocksDb,
DeepProjectId::DuckDb,
DeepProjectId::ClickHouse,
DeepProjectId::ScyllaDb,
] {
let name = id.display_name();
assert!(!name.is_empty(), "Missing display name for {:?}", id);
}
}
#[test]
fn test_project_id_round_trip() {
for id_str in DEEP_PROJECT_IDS {
let id = DeepProjectId::from_str(id_str).unwrap();
assert_eq!(id.as_str(), id_str);
}
}
#[test]
fn test_all_simd_levels_have_mappings() {
let levels = [
DeepSimdLevel::None,
DeepSimdLevel::Mmx,
DeepSimdLevel::Sse,
DeepSimdLevel::Sse2,
DeepSimdLevel::Sse3,
DeepSimdLevel::Ssse3,
DeepSimdLevel::Sse41,
DeepSimdLevel::Sse42,
DeepSimdLevel::Avx,
DeepSimdLevel::Avx2,
DeepSimdLevel::Avx512F,
DeepSimdLevel::Avx512Full,
];
for level in &levels {
let _ = level.to_march_flag();
let _ = level.to_gcc_target_flag();
}
}
#[test]
fn test_build_variant_exhaustive_as_str() {
let variants = [
DeepBuildVariant::Debug,
DeepBuildVariant::Release,
DeepBuildVariant::RelWithDebInfo,
DeepBuildVariant::MinSizeRel,
DeepBuildVariant::PgoInstrumented,
DeepBuildVariant::PgoOptimized,
DeepBuildVariant::Sanitized,
DeepBuildVariant::Fuzz,
DeepBuildVariant::Coverage,
DeepBuildVariant::Custom,
];
for variant in &variants {
let s = variant.as_str();
assert!(!s.is_empty());
}
}
#[test]
fn test_build_status_exhaustive() {
let statuses = [
DeepBuildStatus::Pending,
DeepBuildStatus::Configuring,
DeepBuildStatus::Building,
DeepBuildStatus::Success,
DeepBuildStatus::Failed,
DeepBuildStatus::Skipped,
DeepBuildStatus::Cancelled,
];
for status in &statuses {
let s = status.to_string();
assert!(!s.is_empty());
let _ = status.is_terminal();
let _ = status.is_running();
}
}
#[test]
fn test_sanitizer_exhaustive() {
let sanitizers = [
DeepSanitizer::Address,
DeepSanitizer::Undefined,
DeepSanitizer::Memory,
DeepSanitizer::Thread,
DeepSanitizer::Leak,
DeepSanitizer::HwAddress,
DeepSanitizer::AddressUndefined,
];
for san in &sanitizers {
let flag = san.to_cflag();
assert!(flag.starts_with("-fsanitize="));
}
}
#[test]
fn test_build_system_exhaustive() {
let systems = [
DeepBuildSystem::Cmake,
DeepBuildSystem::Make,
DeepBuildSystem::Autotools,
DeepBuildSystem::Meson,
DeepBuildSystem::Bazel,
DeepBuildSystem::BoostBuild,
DeepBuildSystem::QMake,
DeepBuildSystem::Kbuild,
DeepBuildSystem::Ninja,
DeepBuildSystem::Custom,
];
for sys in &systems {
assert!(!sys.as_str().is_empty());
}
}
#[test]
fn test_test_framework_exhaustive() {
let frameworks = [
DeepTestFramework::Ctest,
DeepTestFramework::GTest,
DeepTestFramework::BoostTest,
DeepTestFramework::Catch2,
DeepTestFramework::PythonUnittest,
DeepTestFramework::ShellScript,
DeepTestFramework::MakeCheck,
DeepTestFramework::Custom,
];
for fw in &frameworks {
assert!(!fw.as_str().is_empty());
}
}
#[test]
fn test_deep_project_id_display_format() {
let id = DeepProjectId::Llvm;
assert_eq!(format!("{}", id), "llvm");
}
#[test]
fn test_deep_build_status_display() {
assert_eq!(format!("{}", DeepBuildStatus::Success), "success");
assert_eq!(format!("{}", DeepBuildStatus::Failed), "failed");
}
#[test]
fn test_x86_diag_level_display() {
assert_eq!(X86DiagLevel::Warning.as_str(), "warning");
assert_eq!(X86DiagLevel::Error.as_str(), "error");
assert_eq!(format!("{}", X86DiagLevel::Note), "note");
}
#[test]
fn test_empty_registry_build_order() {
let registry = test_registry();
let order = registry.build_order();
assert!(order.is_empty());
}
#[test]
fn test_deep_build_report_json_empty() {
let report = DeepBuildReport::new(DeepProjectId::Llvm);
let json = report.to_json();
assert!(json.contains(""project":"llvm""));
assert!(json.contains(""status":"pending""));
}
#[test]
fn test_patch_non_existent_file() {
let tmp = env::temp_dir().join("llvm-native-patch-test");
let _ = fs::create_dir_all(&tmp);
let patch = DeepPatch::new_inline("test", "nonexistent.c", "old", "new");
let result = patch.apply(&tmp);
assert!(result.is_err());
let _ = fs::remove_dir_all(&tmp);
}
#[test]
fn test_deep_stage_report_default() {
let report = DeepStageReport::new(DeepBuildStage::Stage1);
assert_eq!(report.status, DeepBuildStatus::Pending);
assert_eq!(report.tus_compiled, 0);
assert!(report.comparison_passed.is_none());
}
#[test]
fn test_deep_opt_pass_default() {
let pass = DeepOptPass {
name: "TestPass".to_string(),
enabled: true,
effect: "Testing".to_string(),
speedup_pct: Some(10.0),
size_change_pct: Some(-5.0),
};
assert!(pass.enabled);
assert_eq!(pass.speedup_pct, Some(10.0));
}
#[test]
fn test_deep_opt_report_new() {
let report = DeepOptimizationReport::new(DeepProjectId::Ffmpeg);
assert!(!report.pgo_applied);
assert!(!report.lto_applied);
assert_eq!(report.binary_size_bytes, 0);
assert!(report.summary().contains("FFmpeg"));
}
#[test]
fn test_cache_hit_rate_empty() {
let tmp = env::temp_dir().join("llvm-native-cache-empty");
let cache = DeepBuildCache::new(&tmp);
assert!((cache.hit_rate() - 0.0).abs() < f64::EPSILON);
}
#[test]
fn test_x86_target_os_exhaustive() {
let os_list = [
X86TargetOs::Linux,
X86TargetOs::Windows,
X86TargetOs::MacOs,
X86TargetOs::FreeBsd,
X86TargetOs::NetBsd,
X86TargetOs::OpenBsd,
X86TargetOs::Android,
X86TargetOs::Ios,
X86TargetOs::None_,
];
for os in &os_list {
assert!(!os.as_str().is_empty());
assert!(!os.cmake_name().is_empty());
}
}
#[test]
fn test_archive_format_exhaustive() {
let formats = [
ArchiveFormat::TarGz,
ArchiveFormat::TarXz,
ArchiveFormat::TarBz2,
ArchiveFormat::TarZstd,
ArchiveFormat::Zip,
ArchiveFormat::SevenZip,
];
for fmt in &formats {
assert!(!fmt.extension().is_empty());
assert!(!fmt.mime_type().is_empty());
}
}
#[test]
fn test_checksum_algorithm_exhaustive() {
let algos = [
ChecksumAlgorithm::Md5,
ChecksumAlgorithm::Sha1,
ChecksumAlgorithm::Sha256,
ChecksumAlgorithm::Sha512,
ChecksumAlgorithm::Blake3,
];
for algo in &algos {
assert!(!algo.as_str().is_empty());
assert!(!algo.command().is_empty());
}
}
#[test]
fn test_container_runtime_exhaustive() {
let runtimes = [
ContainerRuntime::Docker,
ContainerRuntime::Podman,
ContainerRuntime::Singularity,
ContainerRuntime::Enroot,
];
for rt in &runtimes {
assert!(!rt.command().is_empty());
}
}
#[test]
fn test_ci_system_exhaustive() {
let systems = [
CISystem::GitHubActions,
CISystem::GitLabCI,
CISystem::Jenkins,
CISystem::Buildkite,
CISystem::CircleCI,
CISystem::TravisCI,
CISystem::AzurePipelines,
];
for sys in &systems {
assert!(!sys.as_str().is_empty());
}
}
#[test]
fn test_isolation_type_exhaustive() {
let types = [
IsolationType::None,
IsolationType::Chroot,
IsolationType::SystemdNspawn,
IsolationType::Bubblewrap,
IsolationType::Firejail,
IsolationType::DockerContainer,
];
for t in &types {
let _ = format!("{:?}", t);
}
}
#[test]
fn test_diff_impact_exhaustive() {
let impacts = [
DiffImpact::NoChange,
DiffImpact::Minor,
DiffImpact::Moderate,
DiffImpact::Major,
DiffImpact::Breaking,
];
for imp in &impacts {
assert!(!imp.as_str().is_empty());
assert!(!imp.emoji().is_empty());
}
}
#[test]
fn test_finding_severity_exhaustive() {
let severities = [
FindingSeverity::Note,
FindingSeverity::Warning,
FindingSeverity::Error,
FindingSeverity::Fatal,
];
for _sev in &severities {
let _ = format!("{:?}", _sev);
}
}
#[test]
fn test_all_factory_functions_consistency() {
let factories: Vec<(&str, fn() -> DeepProjectConfig)> = vec![
("llvm", llvm_deep_config),
("llvm-minimal", llvm_minimal_config),
("llvm-fuzz", llvm_fuzz_config),
("llvm-bootstrap", llvm_bootstrap_config),
("linux-kernel", linux_kernel_deep_config),
("linux-kernel-i386", linux_kernel_i386_config),
("qt", qt_deep_config),
("qt-core", qt_core_only_config),
("boost", boost_deep_config),
("ffmpeg", ffmpeg_deep_config),
("ffmpeg-minimal", ffmpeg_minimal_config),
("opencv", opencv_deep_config),
("opencv-cuda", opencv_cuda_config),
("tensorflow-lite", tensorflow_lite_deep_config),
("protobuf", protobuf_deep_config),
("grpc", grpc_deep_config),
("abseil", abseil_deep_config),
("leveldb", leveldb_deep_config),
("rocksdb", rocksdb_deep_config),
("duckdb", duckdb_deep_config),
("clickhouse", clickhouse_deep_config),
("scylladb", scylladb_deep_config),
];
for (label, factory) in factories {
let config = factory();
assert!(
!config.name.is_empty(),
"Factory '{}' produced config with empty name",
label
);
assert!(
!config.version.is_empty(),
"Factory '{}' produced config with empty version",
label
);
}
}
#[test]
fn test_export_build_report_with_test_results() {
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
let mut test_report = DeepTestReport::new(DeepProjectId::Llvm);
test_report.total = 10;
test_report.passed = 9;
test_report.failed = 1;
report.test_report = Some(test_report);
let md = export_build_report(&report, "markdown");
assert!(md.contains("Test Results"));
assert!(md.contains("9/10"));
}
#[test]
fn test_export_build_report_with_optimizations() {
let mut report = DeepBuildReport::new(DeepProjectId::Llvm);
let mut opt_report = DeepOptimizationReport::new(DeepProjectId::Llvm);
opt_report.pgo_applied = true;
opt_report.pgo_speedup_pct = Some(12.0);
report.opt_report = Some(opt_report);
let md = export_build_report(&report, "markdown");
assert!(md.contains("Optimizations"));
}
#[test]
fn test_platform_info_has_cpu_model() {
let info = X86PlatformInfo::detect();
assert!(!info.cpu_model.is_empty(), "CPU model should not be empty");
}
#[test]
fn test_platform_info_has_features() {
let info = X86PlatformInfo::detect();
assert!(
!info.cpu_features.is_empty(),
"CPU features should not be empty"
);
assert!(
info.cpu_features.iter().any(|f| f.contains("sse2")),
"SSE2 should be present on any x86-64 system"
);
}
#[test]
fn test_platform_info_kernel_version() {
let info = X86PlatformInfo::detect();
assert!(
!info.kernel_version.is_empty(),
"Kernel version should not be empty"
);
}
#[test]
fn test_neon_translation_no_change_for_pure_sse() {
let sse_code = "_mm_add_ps(a, b);";
let result = translate_neon_to_sse(sse_code);
assert!(result.contains("_mm_add_ps"));
}
#[test]
fn test_neon_translation_empty_input() {
let result = translate_neon_to_sse("");
assert!(result.is_empty());
}
#[test]
fn test_content_addressed_cache_new() {
let tmp = env::temp_dir().join("llvm-native-cac-test");
let cache = ContentAddressedCache::new(&tmp);
assert!(!cache.writable);
assert_eq!(cache.estimated_size, 0);
assert!(cache.remote_endpoint.is_none());
}
#[test]
fn test_bench_measurement_defaults() {
let measurement = BenchMeasurement {
name: "test_bench".to_string(),
iterations: 100,
real_time_ns: 1000,
cpu_time_ns: 950,
time_unit: "ns".to_string(),
bytes_per_second: 1_000_000,
items_per_second: 500_000,
counters: HashMap::new(),
label: None,
};
assert_eq!(measurement.iterations, 100);
assert!(measurement.real_time_ns > 0);
}
#[test]
fn test_build_profiler_better_score_for_faster_runtime() {
let mut profiler = BuildProfiler::new(DeepProjectId::Llvm);
profiler.add_result(&["-O2".to_string()], 100.0, 50_000_000, 500);
profiler.add_result(&["-O3".to_string()], 100.0, 50_000_000, 1000);
profiler.evaluate();
let best = profiler.best_config.as_ref().unwrap();
assert_eq!(best.runtime_perf_ns_per_iter, 500);
}
#[test]
fn test_scan_non_existent_directory() {
let result = scan_for_projects(Path::new("/nonexistent/path/for/testing"));
match result {
Ok(r) => assert!(r.detected_projects.is_empty()),
Err(_) => { }
}
}
#[test]
fn test_comprehensive_registry_workflow() {
let mut registry = test_registry();
registry.register_default_projects();
registry.init_subsystems();
assert_eq!(registry.projects.len(), 15);
let order = registry.build_order();
assert_eq!(order.len(), 15);
let unique: HashSet<_> = order.iter().copied().collect();
assert_eq!(unique.len(), order.len());
let toolchain = registry.generate_toolchain_file();
assert!(toolchain.contains("clang"));
assert!(toolchain.contains("Linux"));
let presets = generate_cmake_presets(®istry);
assert!(presets.contains("version"));
let issues = registry.validate_dependencies();
let _ = issues.len();
let summary = build_summary(&[]);
assert!(summary.contains("0 total"));
let empty_tests = BTreeMap::new();
let test_summ = test_summary(&empty_tests);
assert!(test_summ.contains("Projects tested: 0"));
}
#[test]
fn test_all_deep_project_ids_enumerable() {
let all_ids = [
DeepProjectId::Llvm,
DeepProjectId::LinuxKernel,
DeepProjectId::Qt,
DeepProjectId::Boost,
DeepProjectId::Ffmpeg,
DeepProjectId::OpenCV,
DeepProjectId::TensorFlowLite,
DeepProjectId::Protobuf,
DeepProjectId::Grpc,
DeepProjectId::Abseil,
DeepProjectId::LevelDb,
DeepProjectId::RocksDb,
DeepProjectId::DuckDb,
DeepProjectId::ClickHouse,
DeepProjectId::ScyllaDb,
];
assert_eq!(all_ids.len(), DEEP_PROJECT_IDS.len());
for id in &all_ids {
assert!(DEEP_PROJECT_IDS.contains(&id.as_str()));
}
}
#[test]
fn test_simd_level_total_order() {
let levels = vec![
DeepSimdLevel::None,
DeepSimdLevel::Mmx,
DeepSimdLevel::Sse,
DeepSimdLevel::Sse2,
DeepSimdLevel::Sse3,
DeepSimdLevel::Ssse3,
DeepSimdLevel::Sse41,
DeepSimdLevel::Sse42,
DeepSimdLevel::Avx,
DeepSimdLevel::Avx2,
DeepSimdLevel::Avx512F,
DeepSimdLevel::Avx512Full,
];
for i in 0..levels.len() - 1 {
assert!(
levels[i + 1] > levels[i],
"{:?} should be greater than {:?}",
levels[i + 1],
levels[i]
);
}
}
#[test]
fn test_deep_build_stage_total_order() {
let stages = vec![
DeepBuildStage::Stage0,
DeepBuildStage::Stage1,
DeepBuildStage::Stage2,
DeepBuildStage::Stage3,
];
for i in 0..stages.len() - 1 {
assert!(
stages[i + 1] > stages[i],
"{:?} should be greater than {:?}",
stages[i + 1],
stages[i]
);
}
assert_eq!(DeepBuildStage::Stage0.index(), 0);
assert_eq!(DeepBuildStage::Stage3.index(), 3);
assert_eq!(DeepBuildStage::Single.index(), 0);
}
#[test]
fn test_patch_categories_constants() {
assert!(!PATCH_CATEGORY_BUILD_FIX.is_empty());
assert!(!PATCH_CATEGORY_COMPATIBILITY.is_empty());
assert!(!PATCH_CATEGORY_PERFORMANCE.is_empty());
assert!(!PATCH_CATEGORY_SECURITY.is_empty());
assert!(!PATCH_CATEGORY_X86_SPECIFIC.is_empty());
assert!(!PATCH_CATEGORY_CLANG_COMPAT.is_empty());
}
#[test]
fn test_deep_lto_config_compiler_flags() {
let mut lto = DeepLtoConfig::default();
lto.enabled = true;
lto.mode = "thin".to_string();
let flags = lto.compiler_flags();
assert!(flags.iter().any(|f| f.contains("flto=thin")));
let linker_flags = lto.linker_flags();
assert!(linker_flags.iter().any(|f| f.contains("flto=thin")));
}
#[test]
fn test_deep_lto_config_full_mode() {
let mut lto = DeepLtoConfig::default();
lto.enabled = true;
lto.mode = "full".to_string();
let flags = lto.compiler_flags();
assert!(flags.iter().any(|f| f.contains("flto=full")));
}
#[test]
fn test_bolt_modes_constant() {
assert!(!BOLT_MODES.is_empty());
assert!(BOLT_MODES.contains(&"hfsort"));
assert!(BOLT_MODES.contains(&"hfsort+"));
assert!(BOLT_MODES.contains(&"cdsplit"));
}
}