/* * Copyright (c) 2024 Emma Tebibyte * 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 * 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::{ Error, Write }, process::{ Command, Stdio }, path::PathBuf, }; use bindgen::{ Builder, CargoCallbacks, MacroTypeVariation }; fn main() -> Result<(), Error> { let mut header = String::new(); /* 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 \n".as_bytes())?; } let output = process.wait_with_output()?.stdout; let headers = String::from_utf8(output).map_err(|e| { Error::other(e.to_string()) })?; /* 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 Rust’s exit() implementation */ let bindings = Builder::default() .use_core() .default_macro_constant_type(MacroTypeVariation::Signed) .header(header) .parse_callbacks(Box::new(CargoCallbacks::new())) .generate() .map_err(|e| Error::other(e.to_string()))?; bindings.write_to_file(PathBuf::from("src/").join("lib.rs"))?; Ok(()) }