libuwebsockets-sys 0.0.1

Native bindings to the uWebSockets CAPI
Documentation
use std::env;
#[cfg(feature = "uws_vendored")]
use std::path::{Path};
use std::path::{PathBuf};
use std::process::Command;

fn main() {
  let cur_dir = env::current_dir().unwrap();
  let host = env::var("HOST").unwrap();
  let target = env::var("TARGET").unwrap();
  let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
  let uws_dir = cur_dir.join("uWebSockets");
  let us_dir = uws_dir.join("uSockets");
  let capi_dir = uws_dir.join("capi");
  let is_windows = host.contains("windows") && target.contains("windows");
  if is_windows {
    panic!("uws-sys is not support windows yet");
  }

  if !uws_dir.exists() {
    if !Command::new("git")
      .args(["submodule", "update", "--init", "uWebSockets"])
      .status()
      .unwrap()
      .success()
    {
      panic!("Can't pull uWebSockets")
    };

    if !Command::new("git")
      .current_dir(uws_dir)
      .args(["submodule", "update", "--init", "uSockets"])
      .status()
      .unwrap()
      .success()
    {
      panic!("Can't pull uSockets")
    }
  }

  bindgen::Builder::default()
    .clang_arg(format!("-I{}", us_dir.join("src").display()))
    .header(capi_dir.join("libuwebsockets.h").display().to_string())
    .parse_callbacks(Box::new(bindgen::CargoCallbacks))
    .generate()
    .expect("Unable to generate bindings")
    .write_to_file(out_dir.join("bindings.rs"))
    .expect("Couldn't write bindings!");

  #[cfg(feature = "uws_vendored")]
  if !Command::new("make")
    .current_dir(&capi_dir)
    .arg("capi")
    .status()
    .expect("Failed to run make")
    .success()
  {
    panic!("Can't build UWS CAPI!");
  }

  #[cfg(feature = "uws_vendored")]
    let is_apple = host.contains("apple") && target.contains("apple");

  #[cfg(feature = "uws_vendored")]
  if is_apple
    && !Command::new("libtool")
    .current_dir(&capi_dir)
    .arg("-static")
    .arg("-o")
    .arg("libuwebsockets.a")
    .arg("libuwebsockets.o")
    .arg("../uSockets/uSockets.a")
    .status()
    .expect("Failed to run libtool")
    .success()
  {
    panic!("Failed to pack libuwebsockets.a");
  }

  #[cfg(feature = "uws_vendored")]
  copy_by_condition(capi_dir, &out_dir, |filename| filename.ends_with(".a"));

  #[cfg(feature = "uws_vendored")]
  println!("cargo:rustc-link-search=native={}", out_dir.display());
  #[cfg(feature = "uws_vendored")]
  println!("cargo:rustc-link-lib=static=uwebsockets");

  println!("cargo:rustc-link-lib=c++");
  println!("cargo:rustc-link-lib=z");
  println!("cargo:rustc-link-lib=uv");
  println!("cargo:rustc-link-lib=crypto");
  println!("cargo:rustc-link-lib=ssl");
}

#[cfg(feature = "uws_vendored")]
fn copy_by_condition<T>(from: impl AsRef<Path>, to: impl AsRef<Path>, condition: T)
  where
    T: Fn(&str) -> bool + Sized + 'static,
{
  use std::fs;
  let entries = from.as_ref().read_dir().unwrap();
  for entry in entries {
    let entry = entry.unwrap();
    if entry.file_type().unwrap().is_dir() {
      continue;
    }

    let file_name = entry.file_name();

    if !condition(file_name.to_str().unwrap()) {
      continue;
    }
    let from = entry.path();
    let to = to.as_ref().join(file_name);
    println!("copy from {from:#?} to: {to:#?}");
    fs::copy(&from, &to).unwrap();
  }
}