Skip to content

Commit b039fed

Browse files
authored
Implement C project generator in Rust
This Rust program generates a C project consisting of three source files (alpha.c, beta.c, runner.c), compiles them into object files, and links them into an executable. It includes error handling for file operations and command execution.
1 parent 2dc3d31 commit b039fed

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

src/main.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use std::fs;
2+
use std::io::Write;
3+
use std::path::PathBuf;
4+
use std::process::Command;
5+
6+
const C_GENERATOR: &str = r#"
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
#include <errno.h>
11+
12+
/* Heresy C generator:
13+
- Writes alpha.c, beta.c, runner.c
14+
- Compiles them to alpha.o, beta.o, runner.o
15+
- Links into heresy_exe
16+
- Optionally tries to call cargo again (disabled by env HERESY_ONCE=1)
17+
*/
18+
19+
static const char *ALPHA_SRC =
20+
"#include <stdio.h>\n"
21+
"void alpha(void){ puts(\"Alpha says hello from heresy.\"); }\n";
22+
23+
static const char *BETA_SRC =
24+
"#include <stdio.h>\n"
25+
"void beta(void){ puts(\"Beta whispers: cargo is a Makefile.\"); }\n";
26+
27+
static const char *RUNNER_SRC =
28+
"#include <stdio.h>\n"
29+
"void alpha(void); void beta(void);\n"
30+
"int main(void){ puts(\">>> runner.c starting\"); alpha(); beta(); puts(\">>> runner.c done\"); return 0; }\n";
31+
32+
static int write_file(const char* path, const char* contents) {
33+
FILE *f = fopen(path, "wb");
34+
if(!f){ fprintf(stderr, \"write_file: fopen %s failed: %s\\n\", path, strerror(errno)); return -1; }
35+
size_t n = fwrite(contents, 1, strlen(contents), f);
36+
if(n != strlen(contents)){ fprintf(stderr, \"write_file: short write %s\\n\", path); fclose(f); return -1; }
37+
fclose(f);
38+
return 0;
39+
}
40+
41+
static int run(const char *cmd) {
42+
int rc = system(cmd);
43+
if(rc != 0){
44+
fprintf(stderr, \"cmd failed (%d): %s\\n\", rc, cmd);
45+
return -1;
46+
}
47+
return 0;
48+
}
49+
50+
int main(void){
51+
puts("🔧 C-generator: emitting tiny C project (alpha,beta,runner)...");
52+
if(write_file("alpha.c", ALPHA_SRC) < 0) return 1;
53+
if(write_file("beta.c", BETA_SRC) < 0) return 1;
54+
if(write_file("runner.c",RUNNER_SRC)< 0) return 1;
55+
56+
puts("🧱 compiling objects...");
57+
if(run("gcc -Wall -g -O0 -c alpha.c -o alpha.o")) return 1;
58+
if(run("gcc -Wall -g -O0 -c beta.c -o beta.o" )) return 1;
59+
if(run("gcc -Wall -g -O0 -c runner.c -o runner.o")) return 1;
60+
61+
puts("🔗 linking heresy_exe...");
62+
if(run("gcc -g -o heresy_exe alpha.o beta.o runner.o")) return 1;
63+
puts("🎉 built ./heresy_exe");
64+
65+
/* Optional ouroboros poke (disabled by HERESY_ONCE=1) */
66+
const char* once = getenv("HERESY_ONCE");
67+
if(!once || strcmp(once, "1") != 0){
68+
puts("♻️ (would re-invoke cargo here, but we're polite in CI)");
69+
// run("cargo build --quiet"); // uncomment for maximum looping chaos (not recommended)
70+
} else {
71+
puts("🛑 recursion guard (HERESY_ONCE=1) active; skipping cargo re-entry.");
72+
}
73+
return 0;
74+
}
75+
"#;
76+
77+
fn sh(cmd: &mut Command) -> std::io::Result<()> {
78+
let status = cmd.status()?;
79+
if !status.success() {
80+
Err(std::io::Error::new(
81+
std::io::ErrorKind::Other,
82+
format!("Command failed: {:?}", cmd),
83+
))
84+
} else {
85+
Ok(())
86+
}
87+
}
88+
89+
fn main() -> std::io::Result<()> {
90+
// Stage dir for the embedded C project
91+
let mut dir = PathBuf::from("target/heresy_c");
92+
fs::create_dir_all(&dir)?;
93+
94+
// Write generator C file
95+
let gen_c = dir.join("heretic_build.c");
96+
{
97+
let mut f = fs::File::create(&gen_c)?;
98+
f.write_all(C_GENERATOR.as_bytes())?;
99+
}
100+
101+
// Compile the generator
102+
println!("🔧 compiling embedded C generator 👉 {}", gen_c.display());
103+
sh(Command::new("gcc")
104+
.arg("-Wall").arg("-g").arg("-O0")
105+
.arg(gen_c.file_name().unwrap())
106+
.arg("-o").arg("heretic_build")
107+
.current_dir(&dir))?;
108+
109+
// Run the generator with recursion guard
110+
println!("🌀 running C generator…");
111+
let mut run_gen = Command::new("./heretic_build");
112+
run_gen.current_dir(&dir);
113+
run_gen.env("HERESY_ONCE", "1");
114+
sh(&mut run_gen)?;
115+
116+
// Show the result
117+
let exe = dir.join("heresy_exe");
118+
println!("✅ generator produced: {}", exe.display());
119+
120+
// Demo run
121+
println!("▶️ executing heresy_exe:");
122+
let out = Command::new(exe).output()?;
123+
print!("{}", String::from_utf8_lossy(&out.stdout));
124+
eprint!("{}", String::from_utf8_lossy(&out.stderr));
125+
126+
println!("🎯 Done. Maximum C-in-Rust heresy achieved.");
127+
Ok(())
128+
}

0 commit comments

Comments
 (0)