1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Build script for seq-compiler
//!
//! Locates the seq-runtime static library so it can be embedded into the compiler.
use std::env;
use std::fs;
use std::path::PathBuf;
fn main() {
// When building for docs.rs, skip runtime embedding entirely
// docs.rs sets DOCS_RS=1 in the environment
if env::var("DOCS_RS").is_ok() {
// Set a dummy path - lib.rs will use cfg(docsrs) to skip include_bytes
println!("cargo:rustc-env=SEQ_RUNTIME_LIB_PATH=/dev/null");
return;
}
// Verify that seq-runtime version matches compiler version
verify_runtime_version();
// Rerun verification if Cargo.toml changes
println!("cargo:rerun-if-changed=Cargo.toml");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
// OUT_DIR is something like:
// target/release/build/seq-compiler-xxx/out
// We need to find libseq_runtime.a in:
// target/release/libseq_runtime.a or target/release/deps/libseq_runtime-xxx.a
// Navigate up from OUT_DIR to find target directory
// OUT_DIR = target/<profile>/build/<pkg>-<hash>/out
let target_dir = out_dir
.parent() // build/<pkg>-<hash>/out -> build/<pkg>-<hash>
.and_then(|p| p.parent()) // -> build
.and_then(|p| p.parent()) // -> <profile> (release/debug)
.expect("Could not find target directory");
// Try to find libseq_runtime.a
let direct_lib = target_dir.join("libseq_runtime.a");
let runtime_lib = if direct_lib.exists() {
direct_lib
} else {
// Search in deps directory for libseq_runtime-*.a
let deps_dir = target_dir.join("deps");
find_runtime_in_deps(&deps_dir).unwrap_or_else(|| {
panic!(
"Runtime library not found.\n\
Looked in: {}\n\
And deps: {}\n\
OUT_DIR was: {}",
direct_lib.display(),
deps_dir.display(),
out_dir.display()
)
})
};
// Set environment variable for include_bytes! in lib.rs
println!(
"cargo:rustc-env=SEQ_RUNTIME_LIB_PATH={}",
runtime_lib.display()
);
// Rerun if the runtime library changes
println!("cargo:rerun-if-changed={}", runtime_lib.display());
}
fn find_runtime_in_deps(deps_dir: &PathBuf) -> Option<PathBuf> {
if !deps_dir.exists() {
return None;
}
fs::read_dir(deps_dir).ok()?.find_map(|entry| {
let entry = entry.ok()?;
let name = entry.file_name();
let name_str = name.to_string_lossy();
if name_str.starts_with("libseq_runtime") && name_str.ends_with(".a") {
Some(entry.path())
} else {
None
}
})
}
/// Verify that the seq-runtime version matches the seq-compiler version
/// by parsing the Cargo.toml files using a proper TOML parser
fn verify_runtime_version() {
let compiler_version = env!("CARGO_PKG_VERSION");
// Read and parse the compiler's Cargo.toml
let cargo_toml_content =
fs::read_to_string("Cargo.toml").expect("Failed to read compiler/Cargo.toml");
let cargo_toml: toml::Value = cargo_toml_content
.parse()
.expect("Failed to parse Cargo.toml");
// Extract the seq-runtime version from build-dependencies
let runtime_version = cargo_toml
.get("build-dependencies")
.and_then(|deps| deps.get("seq-runtime"))
.and_then(|dep| {
// Handle both inline table and string formats
match dep {
toml::Value::Table(t) => t.get("version").and_then(|v| v.as_str()),
toml::Value::String(s) => Some(s.as_str()),
_ => None,
}
})
.expect("Could not find seq-runtime version in Cargo.toml");
// Remove the '=' prefix from exact version requirement
let runtime_version = runtime_version.trim_start_matches('=');
if compiler_version != runtime_version {
panic!(
"\n\n\
╔══════════════════════════════════════════════════════════════╗\n\
║ VERSION MISMATCH ERROR ║\n\
╠══════════════════════════════════════════════════════════════╣\n\
║ seq-compiler version: {:<39}║\n\
║ seq-runtime version: {:<39}║\n\
║ ║\n\
║ The embedded runtime MUST match the compiler version. ║\n\
║ This ensures published crates.io packages are trustworthy. ║\n\
║ ║\n\
║ Update compiler/Cargo.toml to pin seq-runtime to: ║\n\
║ version = \"={:<46}║\n\
╚══════════════════════════════════════════════════════════════╝\n",
compiler_version, runtime_version, compiler_version
);
}
}