/* * __ __ _ _ _ * | \/ | ___ ___ __ _| | (_)_ __ | | __ * | |\/| |/ _ \/ __|/ _` | | | | '_ \| |/ / * | | | | __/\__ \ (_| | |___| | | | | < * |_| |_|\___||___/\__,_|_____|_|_| |_|_|\_\ * * Copyright (c) 2017-2018, The MesaLink Authors. * All rights reserved. * * This work is licensed under the terms of the BSD 3-Clause License. * For a copy, see the LICENSE file. * */ use std::env; use std::fs; use std::io::prelude::*; use std::path::PathBuf; use walkdir::WalkDir; #[cfg(unix)] fn generate_la(lib: &str) -> std::io::Result<()> { use std::fs::File; let self_version = env!("CARGO_PKG_VERSION"); let top_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let profile = env::var("PROFILE").unwrap(); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); let target_dir = match env::var("CARGO_TARGET_SUBDIR") { Ok(dir) => format!("{}/target/{}", top_dir, dir), Err(_) => format!("{}/target/{}", top_dir, profile), }; let libs_dir = format!("{}/.libs", target_dir); let libs_path = PathBuf::from(&libs_dir); let la_path = PathBuf::from(format!("{}/{}.la", target_dir, lib)); let old_lib_path = PathBuf::from(format!("{}/{}.a", target_dir, lib)); let new_lib_path = PathBuf::from(format!("{}/{}.a", libs_dir, lib)); if !libs_path.exists() { fs::create_dir_all(&libs_path)?; } if la_path.exists() { fs::remove_file(&la_path)?; } if new_lib_path.exists() { fs::remove_file(&new_lib_path)?; } let mut file = File::create(&la_path)?; writeln!(file, "# {}.la - a libtool library file", lib)?; writeln!(file, "# Generated by libtool-rust {}", self_version)?; writeln!(file, "dlname=''")?; writeln!(file, "library_names=''")?; writeln!(file, "old_library='{}.a'", lib)?; if target_os == "macos" { writeln!( file, "inherited_linker_flags=' -lm -ldl -lresolv -framework Security'" )?; } else { writeln!(file, "inherited_linker_flags=' -pthread -lm -ldl'")?; } writeln!(file, "installed=no")?; writeln!(file, "shouldnotlink=no")?; std::os::unix::fs::symlink(&old_lib_path, &new_lib_path)?; Ok(()) } #[cfg(windows)] fn generate_la(_lib: &str) -> std::io::Result<()> { Ok(()) } fn generate_headers() -> std::io::Result<()> { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let include_dir = out_dir.join("include"); println!("cargo:rerun-if-changed=mesalink"); let header_files = WalkDir::new("mesalink") .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.file_type().is_file()) .filter(|e| match e.path().extension() { Some(extension) => extension == "h", None => false, }); for src in header_files { let dest = include_dir.join(src.path()); fs::create_dir_all(dest.parent().unwrap())?; fs::copy(src.path(), dest)?; } let version_h = fs::read_to_string("mesalink/version.h.in")?; fs::write( include_dir.join("mesalink/version.h"), version_h.replace("@VERSION@", env::var("CARGO_PKG_VERSION").unwrap().as_str()), )?; let mut options_h = fs::File::create(include_dir.join("mesalink/options.h"))?; options_h.write_all( b"\ #ifndef MESALINK_OPTIONS_H\n\ #define MESALINK_OPTIONS_H\n\n\ #ifdef __cplusplus\n\ extern \"C\" {\n\ #endif\n\n\ ", )?; fn write_define(mut writer: impl Write, name: &str) -> std::io::Result<()> { write!(writer, "\n#undef {}\n#define {}\n", name, name) } if cfg!(feature = "client_apis") { write_define(&mut options_h, "HAVE_CLIENT")?; } else { write_define(&mut options_h, "NO_CLIENT")?; } if cfg!(feature = "server_apis") { write_define(&mut options_h, "HAVE_SERVER")?; } else { write_define(&mut options_h, "NO_SERVER")?; } if cfg!(feature = "error_strings") { write_define(&mut options_h, "HAVE_ERROR_STRINGS")?; } else { write_define(&mut options_h, "NO_ERROR_STRINGS")?; } if cfg!(feature = "aesgcm") { write_define(&mut options_h, "HAVE_AESGCM")?; } else { write_define(&mut options_h, "NO_AESGCM")?; } if cfg!(feature = "chachapoly") { write_define(&mut options_h, "HAVE_CHACHAPOLY")?; } else { write_define(&mut options_h, "NO_CHACHAPOLY")?; } if cfg!(feature = "tls13") { write_define(&mut options_h, "HAVE_TLS13")?; } else { write_define(&mut options_h, "NO_TLS13")?; } if cfg!(feature = "x25519") { write_define(&mut options_h, "HAVE_X25519")?; } else { write_define(&mut options_h, "NO_X25519")?; } if cfg!(feature = "ecdh") { write_define(&mut options_h, "HAVE_ECDH")?; } else { write_define(&mut options_h, "NO_ECDH")?; } if cfg!(feature = "ecdsa") { write_define(&mut options_h, "HAVE_ECDSA")?; } else { write_define(&mut options_h, "NO_ECDSA")?; } if cfg!(feature = "sgx") { write_define(&mut options_h, "HAVE_SGX")?; } else { write_define(&mut options_h, "NO_SGX")?; } options_h.write_all( b"\n\ #ifdef __cplusplus\n\ }\n\ #endif\n\ #endif /* MESALINK_OPTIONS_H */\n\ ", )?; println!("cargo:include={}", include_dir.display()); Ok(()) } fn main() { let lib_name = format!("{}{}", "lib", std::env::var("CARGO_PKG_NAME").unwrap(),); let _ = generate_la(lib_name.as_str()); generate_headers().unwrap(); }