summaryrefslogtreecommitdiff
path: root/build.rs
blob: 75279039c5abd75960f423481f9612045d694c44 (plain)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use std::{env, path::PathBuf, str::FromStr};

fn main() {
    build_butck_ffi();

    #[cfg(target_os = "windows")]
    build_win32_gui();

    #[cfg(target_family = "unix")]
    build_gtk_gui();
}

fn build_butck_ffi() {
    // Check if cbindgen is installed
    let cbindgen_check = std::process::Command::new("cbindgen")
        .arg("--version")
        .output();

    if let Err(e) = cbindgen_check {
        if e.kind() == std::io::ErrorKind::NotFound {
            eprintln!("Error: cbindgen is not installed. Please install it with:");
            eprintln!("    cargo install cbindgen");
            std::process::exit(1);
        } else {
            eprintln!("Error: Failed to check cbindgen installation: {}", e);
            std::process::exit(1);
        }
    }

    let target_dir = get_target_dir();

    // Try to run cbindgen to generate C bindings
    // > cbindgen --config cbindgen.toml ffi --output ffi/.temp/jvlib.h --quiet
    let output = std::process::Command::new("cbindgen")
        .args([
            "--config",
            "cbindgen.toml",
            ".",
            "--output",
            &format!("{}/lib_butck.h", target_dir.display()),
            "--quiet",
        ])
        .output();

    match output {
        Ok(output) if output.status.success() => {
            // Successfully generated bindings
        }
        Ok(_) => {
            eprintln!("cbindgen failed to generate bindings");
        }
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
            eprintln!("cbindgen not found, skipping C binding generation");
        }
        Err(e) => {
            eprintln!("Failed to run cbindgen: {}", e);
        }
    }
}

#[allow(dead_code)]
fn build_win32_gui() {
    use std::fs;
    use std::path::Path;
    use std::process::Command;

    const EXE_NAME: &str = "butckg.exe";

    let crate_root = env!("CARGO_MANIFEST_DIR");
    let build_script = Path::new(crate_root).join("gui\\win32\\scripts\\build.ps1");

    let status = Command::new("powershell")
        .arg("-ExecutionPolicy")
        .arg("Bypass")
        .arg("-File")
        .arg(&build_script)
        .status()
        .expect("Failed to execute build script");

    if !status.success() {
        panic!("Build script failed with exit code: {:?}", status.code());
    }

    let exe_path = Path::new(crate_root)
        .join("gui\\win32\\build\\bin")
        .join(EXE_NAME);
    if exe_path.exists() {
        let target_dir = get_target_dir();

        let dest_path = target_dir.join(EXE_NAME);
        if let Err(e) = fs::copy(&exe_path, &dest_path) {
            panic!("Failed to copy executable to build directory: {}", e);
        }
    } else {
        panic!("Executable not found at: {:?}", exe_path);
    }
}

#[allow(dead_code)]
fn build_gtk_gui() {
    use std::fs;
    use std::path::Path;
    use std::process::Command;

    const EXE_NAME: &str = "butckg";

    let crate_root = env!("CARGO_MANIFEST_DIR");
    let build_script = Path::new(crate_root).join("gui/gtk/cbuild.sh");

    // Check if build script exists
    if !build_script.exists() {
        println!("GTK GUI build script not found, skipping GTK build");
        return;
    }

    // Check if GTK development files are available
    let gtk_check = Command::new("pkg-config")
        .arg("--exists")
        .arg("gtk+-3.0")
        .status();

    if let Ok(status) = gtk_check {
        if !status.success() {
            println!("GTK3 development files not found, skipping GTK build");
            println!("Please install GTK3 development packages:");
            println!("  Ubuntu/Debian: sudo apt-get install libgtk-3-dev");
            println!("  Fedora: sudo dnf install gtk3-devel");
            println!("  Arch: sudo pacman -S gtk3");
            return;
        }
    } else {
        println!("Failed to check GTK3 installation, skipping GTK build");
        return;
    }

    // Make build script executable
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        if let Ok(metadata) = fs::metadata(&build_script) {
            let mut perms = metadata.permissions();
            perms.set_mode(0o755);
            fs::set_permissions(&build_script, perms).ok();
        }
    }

    // Run build script
    let status = Command::new("bash")
        .arg(&build_script)
        .arg("build")
        .status()
        .expect("Failed to execute GTK build script");

    if !status.success() {
        panic!(
            "GTK build script failed with exit code: {:?}",
            status.code()
        );
    }

    let exe_path = Path::new(crate_root)
        .join("gui/gtk/build/bin")
        .join(EXE_NAME);
    if exe_path.exists() {
        let target_dir = get_target_dir();

        let dest_path = target_dir.join(EXE_NAME);
        if let Err(e) = fs::copy(&exe_path, &dest_path) {
            panic!("Failed to copy GTK executable to build directory: {}", e);
        }
    } else {
        panic!("GTK executable not found at: {:?}", exe_path);
    }
}

fn get_target_dir() -> PathBuf {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let out_dir_path = PathBuf::from_str(&out_dir).unwrap();
    out_dir_path
        .parent()
        .unwrap()
        .parent()
        .unwrap()
        .parent()
        .unwrap()
        .to_path_buf()
}