rustexits/build.rs

87 lines
2.8 KiB
Rust
Raw Normal View History

2024-02-11 20:07:09 +00:00
/*
* Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and permission
* notice:
*
* Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: FSFAP
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any
* warranty.
*/
use std::{
io::{ self, Write },
process::{ Command, exit, Stdio },
path::PathBuf,
};
use bindgen::{ Builder, CargoCallbacks, MacroTypeVariation };
fn main() -> Result<(), io::Error> {
let mut header = String::new();
/* bindgen has a dependency on clang for now */
Command::new("clang").spawn().expect("Missing dependency: clang");
/* Locate sysexits.h using cpp(1) */
let mut process = Command::new("cpp")
.arg("-M")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
if let Some(mut child_stdin) = process.stdin.take() {
child_stdin.write_all("#include <sysexits.h>\n".as_bytes())?;
}
let output = process.wait_with_output()?.stdout;
let headers = String::from_utf8(output).unwrap_or_else( |_| {
eprintln!("Output from cpp(1) is invalid UTF-8.");
/* Exit with status 1 because were bootstrapping sysexits.h, silly! */
exit(1);
});
/* Split headers by spaces because cpp(1) returns more than one */
for h in headers.split(' ') {
if h.contains("sysexits.h") {
header = h.trim().to_string();
/* If sysexits.h cannot be located, then use the dummy sysexits.h */
} else { header = "src/sysexits.h".to_string() }
}
/* Make sysexits bindings depend only on core and use signed integers for
* compatibility with Rusts exit() implementation */
let bindings = Builder::default()
.use_core()
.default_macro_constant_type(MacroTypeVariation::Signed)
.header(header)
.parse_callbacks(Box::new(CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings.");
bindings
.write_to_file(PathBuf::from("src/").join("lib.rs"))
.expect("Couldn't write bindings!");
Ok(())
}