<commit_before>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let openssl_root = register_dep("OPENSSL");
    let zlib_root = register_dep("Z");
    let nghttp2_root = register_dep("NGHTTP2");

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");
    }
    if let Some(root) = openssl_root {
        cmd.arg(format!("--with-ssl={}", msys_compatible(&root)));
    }
    if let Some(root) = zlib_root {
        cmd.arg(format!("--with-zlib={}", msys_compatible(&root)));
    }
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        // NOTE GNU terminology
        // BUILD = machine where we are (cross) compiling curl
        // HOST = machine where the compiled curl will be used
        // TARGET = only relevant when compiling compilers
        if target.contains("windows") {
            // curl's configure can't parse `-windows-` triples when used
            // as `--host`s. In those cases we use this combination of
            // `host` and `target` that appears to do the right thing.
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }

    if let Some(root) = nghttp2_root {
        cmd.arg(format!("--with-nghttp2={}", msys_compatible(&root)));
    } else {
        cmd.arg("--without-nghttp2");
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-libpsl");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-unix-sockets");
    cmd.arg("--disable-versioned-symbols");
    cmd.arg("--enable-hidden-symbols");
    cmd.arg("--disable-libcurl-option");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn register_dep(dep: &str) -> Option<PathBuf> {
    if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) {
        prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        return Some(s.into())
    }
    if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) {
        let root = Path::new(&s).parent().unwrap();
        env::set_var(&format!("DEP_{}_ROOT", dep), root);
        let path = root.join("lib/pkgconfig");
        if path.exists() {
            prepend("PKG_CONFIG_PATH", path);
            return Some(root.to_path_buf())
        }
    }

    return None;

    fn prepend(var: &str, val: PathBuf) {
        let prefix = env::var(var).unwrap_or(String::new());
        let mut v = vec![val];
        v.extend(env::split_paths(&prefix));
        env::set_var(var, &env::join_paths(v).unwrap());
    }
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    let features = env::var("CARGO_CFG_TARGET_FEATURE")
                      .unwrap_or(String::new());
    if features.contains("crt-static") {
        cmd.arg("RTLIBCFG=static");
    }

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::copy(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<commit_msg>Qualify link path with `native=`<commit_after>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let openssl_root = register_dep("OPENSSL");
    let zlib_root = register_dep("Z");
    let nghttp2_root = register_dep("NGHTTP2");

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");
    }
    if let Some(root) = openssl_root {
        cmd.arg(format!("--with-ssl={}", msys_compatible(&root)));
    }
    if let Some(root) = zlib_root {
        cmd.arg(format!("--with-zlib={}", msys_compatible(&root)));
    }
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        // NOTE GNU terminology
        // BUILD = machine where we are (cross) compiling curl
        // HOST = machine where the compiled curl will be used
        // TARGET = only relevant when compiling compilers
        if target.contains("windows") {
            // curl's configure can't parse `-windows-` triples when used
            // as `--host`s. In those cases we use this combination of
            // `host` and `target` that appears to do the right thing.
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }

    if let Some(root) = nghttp2_root {
        cmd.arg(format!("--with-nghttp2={}", msys_compatible(&root)));
    } else {
        cmd.arg("--without-nghttp2");
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-libpsl");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-unix-sockets");
    cmd.arg("--disable-versioned-symbols");
    cmd.arg("--enable-hidden-symbols");
    cmd.arg("--disable-libcurl-option");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn register_dep(dep: &str) -> Option<PathBuf> {
    if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) {
        prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        return Some(s.into())
    }
    if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) {
        let root = Path::new(&s).parent().unwrap();
        env::set_var(&format!("DEP_{}_ROOT", dep), root);
        let path = root.join("lib/pkgconfig");
        if path.exists() {
            prepend("PKG_CONFIG_PATH", path);
            return Some(root.to_path_buf())
        }
    }

    return None;

    fn prepend(var: &str, val: PathBuf) {
        let prefix = env::var(var).unwrap_or(String::new());
        let mut v = vec![val];
        v.extend(env::split_paths(&prefix));
        env::set_var(var, &env::join_paths(v).unwrap());
    }
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    let features = env::var("CARGO_CFG_TARGET_FEATURE")
                      .unwrap_or(String::new());
    if features.contains("crt-static") {
        cmd.arg("RTLIBCFG=static");
    }

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::copy(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<|endoftext|>


<commit_before>use diesel;
use diesel::prelude::*;
use rocket_contrib::{JSON, SerdeError};
use uuid::Uuid;

use data::types::*;
use data::modules::get_module_list;
use data::helper::{get_module_dependency_strings, dependencies_fulfilled};
use helpers::db::DB;
use helpers::request::validate_json;
use responses::{APIResponse, accepted, bad_request, created, ok, internal_server_error};
use validation::queue::NewModuleSerializer;

use models::user::User;
use models::module::{NewModule,Module};
use models::research::Research;
use models::resource::Resource;
use models::queue::{QueueEntry, NewQueueEntry};

use schema::modules;
use schema::modules::dsl as module_dsl;
use schema::researches::dsl as research_dsl;
use schema::queue_entries::dsl as queue_entry_dsl;

/// The user needs to be logged in to access this route!
///
/// This route returns the list of all modules and their current levels for the pod of the current user.
#[get("/pod")]
pub fn get_modules(current_user: User, db: DB) -> Result<APIResponse, APIResponse> {

    let pod = current_user.get_pod(&db);
    let modules = pod.get_modules(&db).or(
        Err(ok().message("No modules installed.")))?;

    Ok(ok().data(json!(&modules)))
}

/// Add a new module to pod
///
/// This endpoint:
/// - Checks if dependencies for the module are fulfilled
/// - Checks if there are enough resources
/// - Removes resources from db
/// - Creates a new queue entry for this research
#[post("/pod/new", data = "<request_data>", format = "application/json")]
pub fn add_module(request_data: Result<JSON<NewModuleSerializer>, SerdeError>,
                          current_user: User,
                          db: DB)
                          -> Result<APIResponse, APIResponse> {
    // Unwrap or return specific error if invalid JSON has been sent.
    let module_data = validate_json(request_data)?;

    // Check if the given module name maps to a module type.
    let result = ModuleTypes::from_string(&module_data.module_type);
    let module_type = result.or(Err(bad_request().message(format!("No such module type `{}`",
                                             module_data.module_type)
                                             .as_str())))?;
    let dependency_strings = get_module_dependency_strings(&module_type);

    let (pod, queue) = current_user.get_pod_and_queue(&db);

    let existing_module;
    // Check if there already exists a module for this position
    // We distinguish between stationary and normal modules.

    // Stationary modules have unique names and only exists once
    // per pod.
    if module_data.stationary {
        existing_module = module_dsl::modules
            .count()
            .filter(module_dsl::pod_id.eq(pod.id))
            .filter(module_dsl::name.eq(&module_data.module_type))
            .execute(&*db)
            .unwrap_or(0);
    }
    // Normal modules can exist multiple times. Thereby we just
    // have to check if the requested position is free.
    else {
        existing_module = module_dsl::modules
            .count()
            .filter(module_dsl::pod_id.eq(pod.id))
            .filter(module_dsl::x_pos.eq(module_data.position_x))
            .filter(module_dsl::y_pos.eq(module_data.position_y))
            .execute(&*db)
            .unwrap_or(0);
    };

    // Early return if there already is a module.
    if existing_module != 0 {
        return Err(bad_request().message("There already is a module at this position."));
    }

    // Get the researches the module is depending on
    let dependencies = research_dsl::researches
        .filter(research_dsl::name.eq_any(dependency_strings))
        .get_results::<Research>(&*db);

    // Check if the dependencies are fulfilled.
    // If they're not fulfilled, return a bad request.
    let module_list = get_module_list();
    let fulfilled = dependencies_fulfilled(&module_type,
                                           dependencies,
                                           &module_list);
    if !fulfilled {
        return Err(bad_request().message("Dependencies not fulfilled."));
    }

    // Get cost for level 1
    let level = &module_list.get(&module_type)
          .as_ref()
          .ok_or(internal_server_error())?
          .levels[0];

    // Check if we have enough resources and subtract them.
    let pod_resources = pod.get_resources(&db);
    if level.resources.is_some() && !Resource::check_resources(&level.resources, pod_resources, &db) {
        return Err(bad_request().message("Insufficient resources."));
    }

    // Create the new module
    let new_module = NewModule {
        name: module_data.module_type.clone(),
        stationary: module_data.stationary,
        level: 0,
        x_pos: module_data.position_x,
        y_pos: module_data.position_y,

        pod_id: Some(pod.id),
        base_id: None,
    };
    let module = diesel::insert(&new_module)
        .into(modules::table)
        .get_result::<Module>(&*db)
        .or(Err(internal_server_error()))?;

    // Create a new queue entry with the given module type.
    let new_queue_entry = NewQueueEntry {
        queue_id: queue.id.clone(),
        research_id: None,
        research_name: None,
        module_name: Some(module.name),
        module_id: Some(module.id),
        level: 1,
        duration: level.time,
    };
    queue.add_entry(new_queue_entry, &db);

    Ok(created().message("Queue entry added."))
}

/// Remove module from pod
#[delete("/pod/<module_uuid>")]
pub fn remove_module(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let pod = current_user.get_pod(&db);
    let module = pod.get_module(module_id, &db).or(
        Err(bad_request().message("No module with this id.")))?;

    // Remove queue_entry from database
    diesel::delete(module_dsl::modules
                       .filter(module_dsl::id.eq(module.id)))
            .execute(&*db)
            .or(Err(internal_server_error()))?;

    Ok(accepted().message("Module removed."))
}

/// upgrade module from pod
#[post("/pod/upgrade/<module_uuid>")]
pub fn upgrade_module(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;
    let (pod, queue) = current_user.get_pod_and_queue(&db);

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let module = pod.get_module(module_id, &db).or(
        Err(bad_request().message("No module with this id.")))?;
    let level = module.level + 1;

    // Get all needed info for resource manipulation
    let module_list = get_module_list();
    let pod_resources = pod.get_resources(&db);

    // Add resources from module to pod resources
    let module_type = ModuleTypes::from_string(&module.name)
        .or(Err(internal_server_error()))?;
    let all_levels = &module_list
                          .get(&module_type)
                          .unwrap()
                          .levels;

    // Check if there is a next level.
    if level > all_levels.len() as i32 {
        return Err(bad_request().message("Already at max level"));
    }

    let level_index: usize = (level-1) as usize;
    let costs = &all_levels[level_index].resources;

    if costs.is_some() && !Resource::check_resources(costs, pod_resources, &db) {
        return Err(bad_request().message("Insufficient resources."));
    }

    // Create a new queue entry with the given research type.
    let new_queue_entry = NewQueueEntry {
        queue_id: queue.id.clone(),
        research_id: None,
        research_name: None,
        module_name: Some(module.name),
        module_id: Some(queue.id.clone()),
        level: level,
        duration: all_levels[level_index].time,
    };

    queue.add_entry(new_queue_entry, &db);

    Ok(created().message("Queue entry added."))
}

/// Remove module upgrade from pod queue
#[delete("/pod/upgrade/<module_uuid>")]
pub fn stop_module_upgrade(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;
    let (pod, queue) = current_user.get_pod_and_queue(&db);

    // Get the queue entry
    let queue_entry = queue_entry_dsl::queue_entries
        .filter(queue_entry_dsl::module_id.eq(module_id))
        .filter(queue_entry_dsl::queue_id.eq(queue.id))
        .order(queue_entry_dsl::level.desc())
        .first::<QueueEntry>(&*db)
        .or(Err(bad_request().message("No queue entry with this id.")))?;

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let module = pod.get_module(module_id, &db)
        .or(Err(internal_server_error()))?;

    // Get all needed info for resource manipulation
    let module_list = get_module_list();
    let module_type = ModuleTypes::from_string(&module.name)
        .or(Err(internal_server_error()))?;
    let all_levels = &module_list
                          .get(&module_type)
                          .unwrap()
                          .levels;
    let costs_result = &all_levels[module.level as usize].resources;

    // Refund resources
    let pod_resources = pod.get_resources(&db);
    if let Some(ref costs) = *costs_result {
        Resource::update_resources(costs, pod_resources, false, &db);
    }

    queue.remove_entry(queue_entry.id, &db);

    // Remove module if it's just a upgrade dummy.
    if module.level == 0 {
        diesel::delete(module_dsl::modules
                       .filter(module_dsl::id.eq(module.id)))
            .execute(&*db)
            .or(Err(internal_server_error()))?;
    }

    Ok(accepted().message("Module upgrade stopped."))
}
<commit_msg>Fix count query<commit_after>use diesel;
use diesel::prelude::*;
use rocket_contrib::{JSON, SerdeError};
use uuid::Uuid;

use data::types::*;
use data::modules::get_module_list;
use data::helper::{get_module_dependency_strings, dependencies_fulfilled};
use helpers::db::DB;
use helpers::request::validate_json;
use responses::{APIResponse, accepted, bad_request, created, ok, internal_server_error};
use validation::queue::NewModuleSerializer;

use models::user::User;
use models::module::{NewModule,Module};
use models::research::Research;
use models::resource::Resource;
use models::queue::{QueueEntry, NewQueueEntry};

use schema::modules;
use schema::modules::dsl as module_dsl;
use schema::researches::dsl as research_dsl;
use schema::queue_entries::dsl as queue_entry_dsl;

/// The user needs to be logged in to access this route!
///
/// This route returns the list of all modules and their current levels for the pod of the current user.
#[get("/pod")]
pub fn get_modules(current_user: User, db: DB) -> Result<APIResponse, APIResponse> {

    let pod = current_user.get_pod(&db);
    let modules = pod.get_modules(&db).or(
        Err(ok().message("No modules installed.")))?;

    Ok(ok().data(json!(&modules)))
}

/// Add a new module to pod
///
/// This endpoint:
/// - Checks if dependencies for the module are fulfilled
/// - Checks if there are enough resources
/// - Removes resources from db
/// - Creates a new queue entry for this research
#[post("/pod/new", data = "<request_data>", format = "application/json")]
pub fn add_module(request_data: Result<JSON<NewModuleSerializer>, SerdeError>,
                          current_user: User,
                          db: DB)
                          -> Result<APIResponse, APIResponse> {
    // Unwrap or return specific error if invalid JSON has been sent.
    let module_data = validate_json(request_data)?;

    // Check if the given module name maps to a module type.
    let result = ModuleTypes::from_string(&module_data.module_type);
    let module_type = result.or(Err(bad_request().message(format!("No such module type `{}`",
                                             module_data.module_type)
                                             .as_str())))?;
    let dependency_strings = get_module_dependency_strings(&module_type);

    let (pod, queue) = current_user.get_pod_and_queue(&db);

    let existing_module: i64;
    // Check if there already exists a module for this position
    // We distinguish between stationary and normal modules.

    // Stationary modules have unique names and only exists once
    // per pod.
    if module_data.stationary {
        existing_module = module_dsl::modules
            .count()
            .filter(module_dsl::pod_id.eq(pod.id))
            .filter(module_dsl::name.eq(&module_data.module_type))
            .get_result(&*db)
            .unwrap_or(0);
    }
    // Normal modules can exist multiple times. Thereby we just
    // have to check if the requested position is free.
    else {
        existing_module = module_dsl::modules
            .count()
            .filter(module_dsl::pod_id.eq(pod.id))
            .filter(module_dsl::x_pos.eq(module_data.position_x))
            .filter(module_dsl::y_pos.eq(module_data.position_y))
            .get_result(&*db)
            .unwrap_or(0);
    };

    // Early return if there already is a module.
    if existing_module != 0 {
        return Err(bad_request().message("There already is a module at this position."));
    }

    // Get the researches the module is depending on
    let dependencies = research_dsl::researches
        .filter(research_dsl::name.eq_any(dependency_strings))
        .get_results::<Research>(&*db);

    // Check if the dependencies are fulfilled.
    // If they're not fulfilled, return a bad request.
    let module_list = get_module_list();
    let fulfilled = dependencies_fulfilled(&module_type,
                                           dependencies,
                                           &module_list);
    if !fulfilled {
        return Err(bad_request().message("Dependencies not fulfilled."));
    }

    // Get cost for level 1
    let level = &module_list.get(&module_type)
          .as_ref()
          .ok_or(internal_server_error())?
          .levels[0];

    // Check if we have enough resources and subtract them.
    let pod_resources = pod.get_resources(&db);
    if level.resources.is_some() && !Resource::check_resources(&level.resources, pod_resources, &db) {
        return Err(bad_request().message("Insufficient resources."));
    }

    // Create the new module
    let new_module = NewModule {
        name: module_data.module_type.clone(),
        stationary: module_data.stationary,
        level: 0,
        x_pos: module_data.position_x,
        y_pos: module_data.position_y,

        pod_id: Some(pod.id),
        base_id: None,
    };
    let module = diesel::insert(&new_module)
        .into(modules::table)
        .get_result::<Module>(&*db)
        .or(Err(internal_server_error()))?;

    // Create a new queue entry with the given module type.
    let new_queue_entry = NewQueueEntry {
        queue_id: queue.id.clone(),
        research_id: None,
        research_name: None,
        module_name: Some(module.name),
        module_id: Some(module.id),
        level: 1,
        duration: level.time,
    };
    queue.add_entry(new_queue_entry, &db);

    Ok(created().message("Queue entry added."))
}

/// Remove module from pod
#[delete("/pod/<module_uuid>")]
pub fn remove_module(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let pod = current_user.get_pod(&db);
    let module = pod.get_module(module_id, &db).or(
        Err(bad_request().message("No module with this id.")))?;

    // Remove queue_entry from database
    diesel::delete(module_dsl::modules
                       .filter(module_dsl::id.eq(module.id)))
            .execute(&*db)
            .or(Err(internal_server_error()))?;

    Ok(accepted().message("Module removed."))
}

/// upgrade module from pod
#[post("/pod/upgrade/<module_uuid>")]
pub fn upgrade_module(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;
    let (pod, queue) = current_user.get_pod_and_queue(&db);

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let module = pod.get_module(module_id, &db).or(
        Err(bad_request().message("No module with this id.")))?;
    let level = module.level + 1;

    // Get all needed info for resource manipulation
    let module_list = get_module_list();
    let pod_resources = pod.get_resources(&db);

    // Add resources from module to pod resources
    let module_type = ModuleTypes::from_string(&module.name)
        .or(Err(internal_server_error()))?;
    let all_levels = &module_list
                          .get(&module_type)
                          .unwrap()
                          .levels;

    // Check if there is a next level.
    if level > all_levels.len() as i32 {
        return Err(bad_request().message("Already at max level"));
    }

    let level_index: usize = (level-1) as usize;
    let costs = &all_levels[level_index].resources;

    if costs.is_some() && !Resource::check_resources(costs, pod_resources, &db) {
        return Err(bad_request().message("Insufficient resources."));
    }

    // Create a new queue entry with the given research type.
    let new_queue_entry = NewQueueEntry {
        queue_id: queue.id.clone(),
        research_id: None,
        research_name: None,
        module_name: Some(module.name),
        module_id: Some(queue.id.clone()),
        level: level,
        duration: all_levels[level_index].time,
    };

    queue.add_entry(new_queue_entry, &db);

    Ok(created().message("Queue entry added."))
}

/// Remove module upgrade from pod queue
#[delete("/pod/upgrade/<module_uuid>")]
pub fn stop_module_upgrade(module_uuid: String, current_user: User, db: DB) -> Result<APIResponse, APIResponse> {
    // Parse and check if we got a valid id
    let module_id = Uuid::parse_str(&module_uuid.as_str()).or(
        Err(bad_request().message("Got an invalid uuid")))?;
    let (pod, queue) = current_user.get_pod_and_queue(&db);

    // Get the queue entry
    let queue_entry = queue_entry_dsl::queue_entries
        .filter(queue_entry_dsl::module_id.eq(module_id))
        .filter(queue_entry_dsl::queue_id.eq(queue.id))
        .order(queue_entry_dsl::level.desc())
        .first::<QueueEntry>(&*db)
        .or(Err(bad_request().message("No queue entry with this id.")))?;

    // Get the module and get it from the pod to ensure this is a request from
    // the owner of the module
    let module = pod.get_module(module_id, &db)
        .or(Err(internal_server_error()))?;

    // Get all needed info for resource manipulation
    let module_list = get_module_list();
    let module_type = ModuleTypes::from_string(&module.name)
        .or(Err(internal_server_error()))?;
    let all_levels = &module_list
                          .get(&module_type)
                          .unwrap()
                          .levels;
    let costs_result = &all_levels[module.level as usize].resources;

    // Refund resources
    let pod_resources = pod.get_resources(&db);
    if let Some(ref costs) = *costs_result {
        Resource::update_resources(costs, pod_resources, false, &db);
    }

    queue.remove_entry(queue_entry.id, &db);

    // Remove module if it's just a upgrade dummy.
    if module.level == 0 {
        diesel::delete(module_dsl::modules
                       .filter(module_dsl::id.eq(module.id)))
            .execute(&*db)
            .or(Err(internal_server_error()))?;
    }

    Ok(accepted().message("Module upgrade stopped."))
}
<|endoftext|>


<commit_before>use std::str::FromStr;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub enum Type {
    Address,
    Boolean,
    Float,
    Integer,
    Color,
    Char,
    Undefined,
}

impl FromStr for Type {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "addr" => Ok(Type::Address),
            "bool" => Ok(Type::Boolean),
            "float" => Ok(Type::Float),
            "sig" => Ok(Type::Integer),
            "color" => Ok(Type::Color),
            "char" => Ok(Type::Char),
            _ => Err("unable to parse type"),
        }
    }
}
<commit_msg>fixed wrong cast type<commit_after>use std::str::FromStr;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub enum Type {
    Address,
    Boolean,
    Float,
    Integer,
    Color,
    Char,
    Undefined,
}

impl FromStr for Type {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "addr" => Ok(Type::Address),
            "bool" => Ok(Type::Boolean),
            "float" => Ok(Type::Float),
            "int" => Ok(Type::Integer),
            "color" => Ok(Type::Color),
            "char" => Ok(Type::Char),
            _ => Err("unable to parse type"),
        }
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate gcc;

use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::env;

/// Use the ISPC compiler to compile all ISPC files into object files on Linux
/// Returns true if all ISPC files compiled, or false immediately after one fails to compile
/// Object files will be written to $OUT_DIR/<file_name>.o and headers to
/// $OUT_DIR/<file_name>.h
fn compile_ispc(srcs: &Vec<PathBuf>) -> bool {
    // TODO: again should push into a struct that keeps this state
    let out_dir = env::var("OUT_DIR").unwrap();
    let debug = env::var("DEBUG").unwrap();
    let opt_level = env::var("OPT_LEVEL").unwrap();

    let mut ispc_args = Vec::new();
    if debug == "true" {
        ispc_args.push("-g");
    }
    if opt_level == "0" {
        ispc_args.push("-O0");
    } else if opt_level == "1" {
        ispc_args.push("-O1");
    } else if opt_level == "2" {
        ispc_args.push("-O2");
    } else if opt_level == "3" {
        ispc_args.push("-O3");
    }
    // If we're on Unix we need position independent code
    if cfg!(unix) {
        ispc_args.push("--pic");
    }

    for s in srcs {
        let fname = s.file_name().expect("ISPC source files must be files")
            .to_str().expect("ISPC source file names must be valid UTF-8");

        let status = Command::new("ispc").args(&ispc_args[..])
            .arg(s)
            .args(&["-o", &format!("{}/{}.o", out_dir, fname)])
            .args(&["-h", &format!("{}/{}.h", out_dir, fname)])
            .status().unwrap();
        if !status.success() {
            return false;
        }
    }
    true
}
/// Link the ISPC code into a static library on Unix using `ar`
#[cfg(unix)]
fn link_ispc(lib_name: &str, objs: &Vec<String>) -> ExitStatus {
    // TODO: should push into a struct
    let out_dir = env::var("OUT_DIR").unwrap();
    let mut args = Vec::with_capacity(2 + objs.len());
    args.push(String::from("crus"));
    args.push(String::from("lib") + lib_name + ".a");
    for o in objs {
        args.push(o.clone());
    }
    Command::new("ar").args(&args[..])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap()
}
/// Link the ISPC code into a static library on Windows using `lib.exe`
#[cfg(windows)]
fn link_ispc(lib_name: &str, objs: &Vec<String>) -> ExitStatus {
    let out_dir = env::var("OUT_DIR").unwrap();
    let target = env::var("TARGET").unwrap();
    let lib_cmd = gcc::windows_registry::find_tool(&target[..], "lib.exe")
        .expect("Failed to find lib.exe for MSVC toolchain, aborting");
    let mut args = Vec::with_capacity(2 + objs.len());
    println!("Linker command = {:?}", lib_cmd.path());
    args.push(String::from("/OUT:") + lib_name + ".lib");
    args.push(String::from("/MACHINE:x64"));
    for o in objs {
        args.push(o.clone());
    }
    lib_cmd.to_command().args(&args[..])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap()
}
// Generate Rust bindings for each ISPC file we compiled into the library
fn generate_bindings(lib_name: &str, srcs: &Vec<PathBuf>) -> bool {
    let out_dir = env::var("OUT_DIR").unwrap();
    for s in srcs {
        let fname = s.file_name().expect("ISPC source files must be files")
            .to_str().expect("ISPC source file names must be valid UTF-8");
        let mut bindings = bindgen::builder();
        bindings.forbid_unknown_types()
            .header(format!("{}/{}.h", out_dir, fname))
            .link_static(lib_name);
        match bindings.generate() {
            Ok(b) => b.write_to_file(Path::new(&format!("{}/{}.rs", out_dir, fname))).unwrap(),
            Err(_) => return false,
        };
    }
    true
}

fn main() {
    println!("cargo:rerun-if-changed=src/say_hello.ispc");

    let out_dir = env::var("OUT_DIR").unwrap();

    // Invoke ISPC to compile our code
    let ispc_files = vec![PathBuf::from("src/say_hello.ispc")];
    let ispc_status = compile_ispc(&ispc_files);
    if !ispc_status {
        panic!("ISPC compilation failed");
    }

    // Place our code into a static library we can link against
    if !link_ispc("say_hello", &vec![String::from("say_hello.o")]).success() {
        panic!("Linking ISPC code into archive failed");
    }
    println!("cargo:rustc-flags=-L native={}", out_dir);

    // Generate Rust bindings for the header
    generate_bindings("say_hello", &ispc_files);
}

<commit_msg>Machine flag is unecessary<commit_after>extern crate bindgen;
extern crate gcc;

use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::env;

/// Use the ISPC compiler to compile all ISPC files into object files on Linux
/// Returns true if all ISPC files compiled, or false immediately after one fails to compile
/// Object files will be written to $OUT_DIR/<file_name>.o and headers to
/// $OUT_DIR/<file_name>.h
fn compile_ispc(srcs: &Vec<PathBuf>) -> bool {
    // TODO: again should push into a struct that keeps this state
    let out_dir = env::var("OUT_DIR").unwrap();
    let debug = env::var("DEBUG").unwrap();
    let opt_level = env::var("OPT_LEVEL").unwrap();

    let mut ispc_args = Vec::new();
    if debug == "true" {
        ispc_args.push("-g");
    }
    if opt_level == "0" {
        ispc_args.push("-O0");
    } else if opt_level == "1" {
        ispc_args.push("-O1");
    } else if opt_level == "2" {
        ispc_args.push("-O2");
    } else if opt_level == "3" {
        ispc_args.push("-O3");
    }
    // If we're on Unix we need position independent code
    if cfg!(unix) {
        ispc_args.push("--pic");
    }

    for s in srcs {
        let fname = s.file_name().expect("ISPC source files must be files")
            .to_str().expect("ISPC source file names must be valid UTF-8");

        let status = Command::new("ispc").args(&ispc_args[..])
            .arg(s)
            .args(&["-o", &format!("{}/{}.o", out_dir, fname)])
            .args(&["-h", &format!("{}/{}.h", out_dir, fname)])
            .status().unwrap();
        if !status.success() {
            return false;
        }
    }
    true
}
/// Link the ISPC code into a static library on Unix using `ar`
#[cfg(unix)]
fn link_ispc(lib_name: &str, objs: &Vec<String>) -> ExitStatus {
    // TODO: should push into a struct
    let out_dir = env::var("OUT_DIR").unwrap();
    let mut args = Vec::with_capacity(2 + objs.len());
    args.push(String::from("crus"));
    args.push(String::from("lib") + lib_name + ".a");
    for o in objs {
        args.push(o.clone());
    }
    Command::new("ar").args(&args[..])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap()
}
/// Link the ISPC code into a static library on Windows using `lib.exe`
#[cfg(windows)]
fn link_ispc(lib_name: &str, objs: &Vec<String>) -> ExitStatus {
    let out_dir = env::var("OUT_DIR").unwrap();
    let target = env::var("TARGET").unwrap();
    let lib_cmd = gcc::windows_registry::find_tool(&target[..], "lib.exe")
        .expect("Failed to find lib.exe for MSVC toolchain, aborting");
    let mut args = Vec::with_capacity(2 + objs.len());
    println!("Linker command = {:?}", lib_cmd.path());
    args.push(String::from("/OUT:") + lib_name + ".lib");
    for o in objs {
        args.push(o.clone());
    }
    lib_cmd.to_command().args(&args[..])
        .current_dir(&Path::new(&out_dir))
        .status().unwrap()
}
// Generate Rust bindings for each ISPC file we compiled into the library
fn generate_bindings(lib_name: &str, srcs: &Vec<PathBuf>) -> bool {
    let out_dir = env::var("OUT_DIR").unwrap();
    for s in srcs {
        let fname = s.file_name().expect("ISPC source files must be files")
            .to_str().expect("ISPC source file names must be valid UTF-8");
        let mut bindings = bindgen::builder();
        bindings.forbid_unknown_types()
            .header(format!("{}/{}.h", out_dir, fname))
            .link_static(lib_name);
        match bindings.generate() {
            Ok(b) => b.write_to_file(Path::new(&format!("{}/{}.rs", out_dir, fname))).unwrap(),
            Err(_) => return false,
        };
    }
    true
}

fn main() {
    println!("cargo:rerun-if-changed=src/say_hello.ispc");

    let out_dir = env::var("OUT_DIR").unwrap();

    // Invoke ISPC to compile our code
    let ispc_files = vec![PathBuf::from("src/say_hello.ispc")];
    let ispc_status = compile_ispc(&ispc_files);
    if !ispc_status {
        panic!("ISPC compilation failed");
    }

    // Place our code into a static library we can link against
    if !link_ispc("say_hello", &vec![String::from("say_hello.o")]).success() {
        panic!("Linking ISPC code into archive failed");
    }
    println!("cargo:rustc-flags=-L native={}", out_dir);

    // Generate Rust bindings for the header
    generate_bindings("say_hello", &ispc_files);
}

<|endoftext|>


<commit_before>use std::process::Command;

fn main() {
    let status = Command::new("ld")
        .arg("-lcpufreq").status().unwrap();

    if status.success() {
        println!("cargo:rustc-link-lib=cpufreq");
    } else {
        println!("cargo:rustc-link-lib=cpupower");
    }
}
<commit_msg>Made cpufreq as a default<commit_after>use std::process::Command;

fn main() {
    let status = Command::new("ld")
        .arg("-lcpupower").status().unwrap();

    if status.success() {
        println!("cargo:rustc-link-lib=cpupower");
    } else {
        println!("cargo:rustc-link-lib=cpufreq");
    }
}
<|endoftext|>


<commit_before>use std::env::var;
use std::ascii::AsciiExt;

fn main() {
    // Format: CARGO_BLAS_IMPL = (STATIC|DYLIB)_(BLAS_NAME)
    let lib = match var("CARGO_BLAS_IMPL") {
        Ok(s) => s,
        Err(_) => "DYLIB_BLAS".into(),
    };

    let mut pieces = lib.split("_");
    let link_type = match pieces.next() {
        Some(t) => {
            if t == "STATIC" {
                "static"
            } else if t == "DYLIB" {
                "dylib"
            } else {
                panic!("Link type must be either STATIC or DYLIB")
            }
        },
        None => panic!("Format error"),
    };
    let link_name = match pieces.next() {
        Some(t) => t.to_ascii_lowercase(),
        None => panic!("Format error"),
    };

    println!("cargo:rustc-link-lib={}={}", link_type, link_name);
}
<commit_msg>Simplify env vars<commit_after>use std::env::var;

fn main() {
    let link_type = env_or_default("CARGO_BLAS_TYPE", "dylib");
    let link_name = env_or_default("CARGO_BLAS", "blas");

    println!("cargo:rustc-link-lib={}={}", link_type, link_name);
}

fn env_or_default(var_name: &str, default: &str) -> String {
    match var(var_name) {
        Ok(s) => s,
        Err(_) => default.into(),
    }
}
<|endoftext|>


<commit_before>use std::os;
use std::old_io::fs::PathExtensions;

fn main() {
    let clang_dir = if let Some(dir) = os::getenv("LIBCLANG_PATH") {
        dir
    } else if cfg!(any(target_os = "linux", target_os = "freebsd")) {
        "/usr/lib".to_string()
    } else if cfg!(target_os = "macos") {
        "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib".to_string()
    } else {
        panic!("Platform not supported");
    };

    let clang_dir = Path::new(clang_dir);

    let clang_lib = os::dll_filename("clang");

    let clang_path = clang_dir.join(clang_lib.clone());
    if !clang_path.exists() {
        panic!("Unable to find {}", clang_lib);
    }

    println!("cargo:rustc-flags=-l clang -L {}", clang_dir.as_str().unwrap());
}
<commit_msg>Make build script search on multiple directories on Linux<commit_after>use std::os;
use std::old_io::fs::PathExtensions;

const LINUX_CLANG_DIRS: &'static [&'static str] = &["/usr/lib", "/usr/lib/llvm", "/usr/lib64/llvm"];
const MAC_CLANG_DIR: &'static str = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib";

fn main() {
    let possible_clang_dirs = if let Some(dir) = os::getenv("LIBCLANG_PATH") {
        vec![dir]
    } else if cfg!(any(target_os = "linux", target_os = "freebsd")) {
        LINUX_CLANG_DIRS.iter().map(ToString::to_string).collect()
    } else if cfg!(target_os = "macos") {
        vec![MAC_CLANG_DIR.to_string()]
    } else {
        panic!("Platform not supported");
    };

    let clang_lib = os::dll_filename("clang");

    let maybe_clang_dir = possible_clang_dirs.into_iter().filter_map(|candidate_dir| {
        let clang_dir = Path::new(candidate_dir);
        let clang_path = clang_dir.join(clang_lib.clone());

        if clang_path.exists() {
            Some(clang_dir)
        } else {
            None
        }
    }).next();

    if let Some(clang_dir) = maybe_clang_dir {
        println!("cargo:rustc-flags=-l clang -L {}", clang_dir.as_str().unwrap());
    } else {
        panic!("Unable to find {}", clang_lib);
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;

fn main() {
    match pkg_config::find_library("libR") {
        Ok(..) => return,
        Err(e) => panic!("Couldn't find libR from \
                           pkgconfig ({:?}), failed", e),
    }
}
<commit_msg>Cargo fmt<commit_after>extern crate pkg_config;

fn main() {
    match pkg_config::find_library("libR") {
        Ok(..) => return,
        Err(e) => panic!("Couldn't find libR from pkgconfig ({:?}), failed", e),
    }
}
<|endoftext|>


<commit_before>//! This is a small server which is intended to run inside of an emulator or
//! on a remote test device. This server pairs with the `remote-test-client`
//! program in this repository. The `remote-test-client` connects to this
//! server over a TCP socket and performs work such as:
//!
//! 1. Pushing shared libraries to the server
//! 2. Running tests through the server
//!
//! The server supports running tests concurrently and also supports tests
//! themselves having support libraries. All data over the TCP sockets is in a
//! basically custom format suiting our needs.

#![deny(warnings)]

#[cfg(not(windows))]
use std::fs::Permissions;
#[cfg(not(windows))]
use std::os::unix::prelude::*;

use std::cmp;
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::net::{TcpListener, TcpStream};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

static TEST: AtomicUsize = AtomicUsize::new(0);

struct Config {
    pub remote: bool,
    pub verbose: bool,
}

impl Config {
    pub fn default() -> Config {
        Config { remote: false, verbose: false }
    }

    pub fn parse_args() -> Config {
        let mut config = Config::default();

        let args = env::args().skip(1);
        for argument in args {
            match &argument[..] {
                "remote" => {
                    config.remote = true;
                }
                "verbose" | "-v" => {
                    config.verbose = true;
                }
                arg => panic!("unknown argument: {}", arg),
            }
        }

        config
    }
}

fn main() {
    println!("starting test server");

    let config = Config::parse_args();

    let bind_addr = if cfg!(target_os = "android") || cfg!(windows) || config.remote {
        "0.0.0.0:12345"
    } else {
        "10.0.2.15:12345"
    };

    let listener = t!(TcpListener::bind(bind_addr));
    let (work, tmp): (PathBuf, PathBuf) = if cfg!(target_os = "android") {
        ("/data/tmp/work".into(), "/data/tmp/work/tmp".into())
    } else {
        let mut work_dir = env::temp_dir();
        work_dir.push("work");
        let mut tmp_dir = work_dir.clone();
        tmp_dir.push("tmp");
        (work_dir, tmp_dir)
    };
    println!("listening!");

    t!(fs::create_dir_all(&work));
    t!(fs::create_dir_all(&tmp));

    let lock = Arc::new(Mutex::new(()));

    for socket in listener.incoming() {
        let mut socket = t!(socket);
        let mut buf = [0; 4];
        if socket.read_exact(&mut buf).is_err() {
            continue;
        }
        if &buf[..] == b"ping" {
            t!(socket.write_all(b"pong"));
        } else if &buf[..] == b"push" {
            handle_push(socket, &work);
        } else if &buf[..] == b"run " {
            let lock = lock.clone();
            let work = work.clone();
            let tmp = tmp.clone();
            thread::spawn(move || handle_run(socket, &work, &tmp, &lock));
        } else {
            panic!("unknown command {:?}", buf);
        }
    }
}

fn handle_push(socket: TcpStream, work: &Path) {
    let mut reader = BufReader::new(socket);
    recv(&work, &mut reader);

    let mut socket = reader.into_inner();
    t!(socket.write_all(b"ack "));
}

struct RemoveOnDrop<'a> {
    inner: &'a Path,
}

impl Drop for RemoveOnDrop<'_> {
    fn drop(&mut self) {
        t!(fs::remove_dir_all(self.inner));
    }
}

fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>) {
    let mut arg = Vec::new();
    let mut reader = BufReader::new(socket);

    // Allocate ourselves a directory that we'll delete when we're done to save
    // space.
    let n = TEST.fetch_add(1, Ordering::SeqCst);
    let path = work.join(format!("test{}", n));
    t!(fs::create_dir(&path));
    let _a = RemoveOnDrop { inner: &path };

    // First up we'll get a list of arguments delimited with 0 bytes. An empty
    // argument means that we're done.
    let mut args = Vec::new();
    while t!(reader.read_until(0, &mut arg)) > 1 {
        args.push(t!(str::from_utf8(&arg[..arg.len() - 1])).to_string());
        arg.truncate(0);
    }

    // Next we'll get a bunch of env vars in pairs delimited by 0s as well
    let mut env = Vec::new();
    arg.truncate(0);
    while t!(reader.read_until(0, &mut arg)) > 1 {
        let key_len = arg.len() - 1;
        let val_len = t!(reader.read_until(0, &mut arg)) - 1;
        {
            let key = &arg[..key_len];
            let val = &arg[key_len + 1..][..val_len];
            let key = t!(str::from_utf8(key)).to_string();
            let val = t!(str::from_utf8(val)).to_string();
            env.push((key, val));
        }
        arg.truncate(0);
    }

    // The section of code from here down to where we drop the lock is going to
    // be a critical section for us. On Linux you can't execute a file which is
    // open somewhere for writing, as you'll receive the error "text file busy".
    // Now here we never have the text file open for writing when we spawn it,
    // so why do we still need a critical section?
    //
    // Process spawning first involves a `fork` on Unix, which clones all file
    // descriptors into the child process. This means that it's possible for us
    // to open the file for writing (as we're downloading it), then some other
    // thread forks, then we close the file and try to exec. At that point the
    // other thread created a child process with the file open for writing, and
    // we attempt to execute it, so we get an error.
    //
    // This race is resolve by ensuring that only one thread can write the file
    // and spawn a child process at once. Kinda an unfortunate solution, but we
    // don't have many other choices with this sort of setup!
    //
    // In any case the lock is acquired here, before we start writing any files.
    // It's then dropped just after we spawn the child. That way we don't lock
    // the execution of the child, just the creation of its files.
    let lock = lock.lock();

    // Next there's a list of dynamic libraries preceded by their filenames.
    while t!(reader.fill_buf())[0] != 0 {
        recv(&path, &mut reader);
    }
    assert_eq!(t!(reader.read(&mut [0])), 1);

    // Finally we'll get the binary. The other end will tell us how big the
    // binary is and then we'll download it all to the exe path we calculated
    // earlier.
    let exe = recv(&path, &mut reader);

    let mut cmd = Command::new(&exe);
    cmd.args(args);
    cmd.envs(env);

    // Support libraries were uploaded to `work` earlier, so make sure that's
    // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
    // had some libs uploaded.
    if cfg!(windows) {
        // On windows, libraries are just searched in the executable directory,
        // system directories, PWD, and PATH, in that order. PATH is the only one
        // we can change for this.
        cmd.env(
            "PATH",
            env::join_paths(
                std::iter::once(work.to_owned())
                    .chain(std::iter::once(path.clone()))
                    .chain(env::split_paths(&env::var_os("PATH").unwrap())),
            )
            .unwrap(),
        );
    } else {
        cmd.env("LD_LIBRARY_PATH", format!("{}:{}", work.display(), path.display()));
    }

    // Some tests assume RUST_TEST_TMPDIR exists
    cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());

    // Spawn the child and ferry over stdout/stderr to the socket in a framed
    // fashion (poor man's style)
    let mut child =
        t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
    drop(lock);
    let mut stdout = child.stdout.take().unwrap();
    let mut stderr = child.stderr.take().unwrap();
    let socket = Arc::new(Mutex::new(reader.into_inner()));
    let socket2 = socket.clone();
    let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
    my_copy(&mut stderr, 1, &*socket);
    thread.join().unwrap();

    // Finally send over the exit status.
    let status = t!(child.wait());

    let (which, code) = get_status_code(&status);

    t!(socket.lock().unwrap().write_all(&[
        which,
        (code >> 24) as u8,
        (code >> 16) as u8,
        (code >> 8) as u8,
        (code >> 0) as u8,
    ]));
}

#[cfg(not(windows))]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
    match status.code() {
        Some(n) => (0, n),
        None => (1, status.signal().unwrap()),
    }
}

#[cfg(windows)]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
    (0, status.code().unwrap())
}

fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
    let mut filename = Vec::new();
    t!(io.read_until(0, &mut filename));

    // We've got some tests with *really* long names. We try to name the test
    // executable the same on the target as it is on the host to aid with
    // debugging, but the targets we're emulating are often more restrictive
    // than the hosts as well.
    //
    // To ensure we can run a maximum number of tests without modifications we
    // just arbitrarily truncate the filename to 50 bytes. That should
    // hopefully allow us to still identify what's running while staying under
    // the filesystem limits.
    let len = cmp::min(filename.len() - 1, 50);
    let dst = dir.join(t!(str::from_utf8(&filename[..len])));
    let amt = read_u32(io) as u64;
    t!(io::copy(&mut io.take(amt), &mut t!(File::create(&dst))));
    set_permissions(&dst);
    dst
}

#[cfg(not(windows))]
fn set_permissions(path: &Path) {
    t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
}
#[cfg(windows)]
fn set_permissions(_path: &Path) {}

fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
    let mut b = [0; 1024];
    loop {
        let n = t!(src.read(&mut b));
        let mut dst = dst.lock().unwrap();
        t!(dst.write_all(&[
            which,
            (n >> 24) as u8,
            (n >> 16) as u8,
            (n >> 8) as u8,
            (n >> 0) as u8,
        ]));
        if n > 0 {
            t!(dst.write_all(&b[..n]));
        } else {
            break;
        }
    }
}

fn read_u32(r: &mut dyn Read) -> u32 {
    let mut len = [0; 4];
    t!(r.read_exact(&mut len));
    ((len[0] as u32) << 24)
        | ((len[1] as u32) << 16)
        | ((len[2] as u32) << 8)
        | ((len[3] as u32) << 0)
}
<commit_msg>tools/remote-test-server: make use of verbose option<commit_after>//! This is a small server which is intended to run inside of an emulator or
//! on a remote test device. This server pairs with the `remote-test-client`
//! program in this repository. The `remote-test-client` connects to this
//! server over a TCP socket and performs work such as:
//!
//! 1. Pushing shared libraries to the server
//! 2. Running tests through the server
//!
//! The server supports running tests concurrently and also supports tests
//! themselves having support libraries. All data over the TCP sockets is in a
//! basically custom format suiting our needs.

#![deny(warnings)]

#[cfg(not(windows))]
use std::fs::Permissions;
#[cfg(not(windows))]
use std::os::unix::prelude::*;

use std::cmp;
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::net::{TcpListener, TcpStream};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

static TEST: AtomicUsize = AtomicUsize::new(0);

#[derive(Copy, Clone)]
struct Config {
    pub remote: bool,
    pub verbose: bool,
}

impl Config {
    pub fn default() -> Config {
        Config { remote: false, verbose: false }
    }

    pub fn parse_args() -> Config {
        let mut config = Config::default();

        let args = env::args().skip(1);
        for argument in args {
            match &argument[..] {
                "remote" => {
                    config.remote = true;
                }
                "verbose" | "-v" => {
                    config.verbose = true;
                }
                arg => panic!("unknown argument: {}", arg),
            }
        }

        config
    }
}

fn print_verbose(s: &str, conf: Config) {
    if conf.verbose {
        println!("{}", s);
    }
}

fn main() {
    println!("starting test server");

    let config = Config::parse_args();

    let bind_addr = if cfg!(target_os = "android") || cfg!(windows) || config.remote {
        "0.0.0.0:12345"
    } else {
        "10.0.2.15:12345"
    };

    let listener = t!(TcpListener::bind(bind_addr));
    let (work, tmp): (PathBuf, PathBuf) = if cfg!(target_os = "android") {
        ("/data/tmp/work".into(), "/data/tmp/work/tmp".into())
    } else {
        let mut work_dir = env::temp_dir();
        work_dir.push("work");
        let mut tmp_dir = work_dir.clone();
        tmp_dir.push("tmp");
        (work_dir, tmp_dir)
    };
    println!("listening on {}!", bind_addr);

    t!(fs::create_dir_all(&work));
    t!(fs::create_dir_all(&tmp));

    let lock = Arc::new(Mutex::new(()));

    for socket in listener.incoming() {
        let mut socket = t!(socket);
        let mut buf = [0; 4];
        if socket.read_exact(&mut buf).is_err() {
            continue;
        }
        if &buf[..] == b"ping" {
            print_verbose("Received ping", config);
            t!(socket.write_all(b"pong"));
        } else if &buf[..] == b"push" {
            handle_push(socket, &work, config);
        } else if &buf[..] == b"run " {
            let lock = lock.clone();
            let work = work.clone();
            let tmp = tmp.clone();
            thread::spawn(move || handle_run(socket, &work, &tmp, &lock, config));
        } else {
            panic!("unknown command {:?}", buf);
        }
    }
}

fn handle_push(socket: TcpStream, work: &Path, config: Config) {
    let mut reader = BufReader::new(socket);
    let dst = recv(&work, &mut reader);
    print_verbose(&format!("push {:#?}", dst), config);

    let mut socket = reader.into_inner();
    t!(socket.write_all(b"ack "));
}

struct RemoveOnDrop<'a> {
    inner: &'a Path,
}

impl Drop for RemoveOnDrop<'_> {
    fn drop(&mut self) {
        t!(fs::remove_dir_all(self.inner));
    }
}

fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, config: Config) {
    let mut arg = Vec::new();
    let mut reader = BufReader::new(socket);

    // Allocate ourselves a directory that we'll delete when we're done to save
    // space.
    let n = TEST.fetch_add(1, Ordering::SeqCst);
    let path = work.join(format!("test{}", n));
    t!(fs::create_dir(&path));
    let _a = RemoveOnDrop { inner: &path };

    // First up we'll get a list of arguments delimited with 0 bytes. An empty
    // argument means that we're done.
    let mut args = Vec::new();
    while t!(reader.read_until(0, &mut arg)) > 1 {
        args.push(t!(str::from_utf8(&arg[..arg.len() - 1])).to_string());
        arg.truncate(0);
    }

    // Next we'll get a bunch of env vars in pairs delimited by 0s as well
    let mut env = Vec::new();
    arg.truncate(0);
    while t!(reader.read_until(0, &mut arg)) > 1 {
        let key_len = arg.len() - 1;
        let val_len = t!(reader.read_until(0, &mut arg)) - 1;
        {
            let key = &arg[..key_len];
            let val = &arg[key_len + 1..][..val_len];
            let key = t!(str::from_utf8(key)).to_string();
            let val = t!(str::from_utf8(val)).to_string();
            env.push((key, val));
        }
        arg.truncate(0);
    }

    // The section of code from here down to where we drop the lock is going to
    // be a critical section for us. On Linux you can't execute a file which is
    // open somewhere for writing, as you'll receive the error "text file busy".
    // Now here we never have the text file open for writing when we spawn it,
    // so why do we still need a critical section?
    //
    // Process spawning first involves a `fork` on Unix, which clones all file
    // descriptors into the child process. This means that it's possible for us
    // to open the file for writing (as we're downloading it), then some other
    // thread forks, then we close the file and try to exec. At that point the
    // other thread created a child process with the file open for writing, and
    // we attempt to execute it, so we get an error.
    //
    // This race is resolve by ensuring that only one thread can write the file
    // and spawn a child process at once. Kinda an unfortunate solution, but we
    // don't have many other choices with this sort of setup!
    //
    // In any case the lock is acquired here, before we start writing any files.
    // It's then dropped just after we spawn the child. That way we don't lock
    // the execution of the child, just the creation of its files.
    let lock = lock.lock();

    // Next there's a list of dynamic libraries preceded by their filenames.
    while t!(reader.fill_buf())[0] != 0 {
        recv(&path, &mut reader);
    }
    assert_eq!(t!(reader.read(&mut [0])), 1);

    // Finally we'll get the binary. The other end will tell us how big the
    // binary is and then we'll download it all to the exe path we calculated
    // earlier.
    let exe = recv(&path, &mut reader);
    print_verbose(&format!("run {:#?}", exe), config);

    let mut cmd = Command::new(&exe);
    cmd.args(args);
    cmd.envs(env);

    // Support libraries were uploaded to `work` earlier, so make sure that's
    // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
    // had some libs uploaded.
    if cfg!(windows) {
        // On windows, libraries are just searched in the executable directory,
        // system directories, PWD, and PATH, in that order. PATH is the only one
        // we can change for this.
        cmd.env(
            "PATH",
            env::join_paths(
                std::iter::once(work.to_owned())
                    .chain(std::iter::once(path.clone()))
                    .chain(env::split_paths(&env::var_os("PATH").unwrap())),
            )
            .unwrap(),
        );
    } else {
        cmd.env("LD_LIBRARY_PATH", format!("{}:{}", work.display(), path.display()));
    }

    // Some tests assume RUST_TEST_TMPDIR exists
    cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());

    // Spawn the child and ferry over stdout/stderr to the socket in a framed
    // fashion (poor man's style)
    let mut child =
        t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
    drop(lock);
    let mut stdout = child.stdout.take().unwrap();
    let mut stderr = child.stderr.take().unwrap();
    let socket = Arc::new(Mutex::new(reader.into_inner()));
    let socket2 = socket.clone();
    let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
    my_copy(&mut stderr, 1, &*socket);
    thread.join().unwrap();

    // Finally send over the exit status.
    let status = t!(child.wait());

    let (which, code) = get_status_code(&status);

    t!(socket.lock().unwrap().write_all(&[
        which,
        (code >> 24) as u8,
        (code >> 16) as u8,
        (code >> 8) as u8,
        (code >> 0) as u8,
    ]));
}

#[cfg(not(windows))]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
    match status.code() {
        Some(n) => (0, n),
        None => (1, status.signal().unwrap()),
    }
}

#[cfg(windows)]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
    (0, status.code().unwrap())
}

fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
    let mut filename = Vec::new();
    t!(io.read_until(0, &mut filename));

    // We've got some tests with *really* long names. We try to name the test
    // executable the same on the target as it is on the host to aid with
    // debugging, but the targets we're emulating are often more restrictive
    // than the hosts as well.
    //
    // To ensure we can run a maximum number of tests without modifications we
    // just arbitrarily truncate the filename to 50 bytes. That should
    // hopefully allow us to still identify what's running while staying under
    // the filesystem limits.
    let len = cmp::min(filename.len() - 1, 50);
    let dst = dir.join(t!(str::from_utf8(&filename[..len])));
    let amt = read_u32(io) as u64;
    t!(io::copy(&mut io.take(amt), &mut t!(File::create(&dst))));
    set_permissions(&dst);
    dst
}

#[cfg(not(windows))]
fn set_permissions(path: &Path) {
    t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
}
#[cfg(windows)]
fn set_permissions(_path: &Path) {}

fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
    let mut b = [0; 1024];
    loop {
        let n = t!(src.read(&mut b));
        let mut dst = dst.lock().unwrap();
        t!(dst.write_all(&[
            which,
            (n >> 24) as u8,
            (n >> 16) as u8,
            (n >> 8) as u8,
            (n >> 0) as u8,
        ]));
        if n > 0 {
            t!(dst.write_all(&b[..n]));
        } else {
            break;
        }
    }
}

fn read_u32(r: &mut dyn Read) -> u32 {
    let mut len = [0; 4];
    t!(r.read_exact(&mut len));
    ((len[0] as u32) << 24)
        | ((len[1] as u32) << 16)
        | ((len[2] as u32) << 8)
        | ((len[3] as u32) << 0)
}
<|endoftext|>


<commit_before><commit_msg>Support multiple clients<commit_after><|endoftext|>


<commit_before>use actions::Action;
use notify::Event;

pub struct PrintAction;

impl PrintAction {
    pub fn new() -> PrintAction {
        PrintAction
    }
}

impl Action for PrintAction {
    fn handle_change(&self, event: &Event) {
        match event.path {
            None => println!("No path for event"),
            Some(ref path) => println!("{} changed", path.to_str().unwrap())
        }
    }
}
<commit_msg>Add event type to output from PrintAction<commit_after>use actions::Action;
use notify::Event;
use notify::op;
use notify::op::Op;

pub struct PrintAction;

impl PrintAction {
    pub fn new() -> PrintAction {
        PrintAction
    }

    pub fn flag_to_str(&self, flag: &Op) -> &'static str {
        match flag {
            &op::CHMOD => "Permissions or timestamps changed",
            &op::CREATE => "File or directory created",
            &op::REMOVE => "File or directory removed",
            &op::RENAME => "File or directory renamed",
            &op::WRITE => "File or diretory written to",
            _ => "Unknown change"
        }
    }
}

impl Action for PrintAction {
    fn handle_change(&self, event: &Event) {
        match event.path {
            None => println!("No path for event"),
            Some(ref path) =>  {
                let message = match event.op {
                    Ok(op) => self.flag_to_str(&op),
                    Err(_) => "Unknown change"
                };

                let path_str = path.to_str().unwrap_or("Unknown path");

                println!("{} on path {:?}", message, path_str)
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;

fn main() -> () {

    if cfg!(feature="blis") {
        //Link with BLIS assuming it is installed to the default location:
        println!("cargo:rustc-link-search=native={}/blis/lib", std::env::home_dir().unwrap().to_str().unwrap() );
        println!("cargo:rustc-link-search=native=/usr/local/lib");
        println!("cargo:rustc-link-lib=static=blis");

        //Needed when BLIS is compiled with GCC and OpenMP:
        println!("cargo:rustc-link-search=native=/usr/lib/gcc/x86_64-linux-gnu/5");
        println!("cargo:rustc-link-lib=dylib=gomp");

        //Use bindgen to create bindings to BLIS's typedefs
        //This allows us to interface with the BLIS micro-kernel
		let bindings = bindgen::Builder::default()
			.header("blis_types_wrapper.h")
            .clang_arg(format!("-I/{}/blis/include/blis", std::env::home_dir().unwrap().to_str().unwrap()))
			.generate()
			.expect("Unable to generate bindings");

        // Write the bindings to the $OUT_DIR/bindings.rs file.
    	let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
    	bindings
			.write_to_file(out_path.join("bindings.rs"))
			.expect("Couldn't write bindings!");

        //Needed for linking with BLIS when it was compiled with icc
        /*
        println!("cargo:rustc-link-lib=static=irc");
        */
    }

    if cfg!(feature="libxsmm"){
        println!("cargo:rustc-link-search=native={}/libxsmm/lib", std::env::home_dir().unwrap().to_str().unwrap() );
        println!("cargo:rustc-link-lib=static=xsmm");
    }
}
<commit_msg>Fix problem where size_t is not defined during bindgen on some systems<commit_after>extern crate bindgen;

fn main() -> () {

    if cfg!(feature="blis") {
        //Link with BLIS assuming it is installed to the default location:
        println!("cargo:rustc-link-search=native={}/blis/lib", std::env::home_dir().unwrap().to_str().unwrap() );
        println!("cargo:rustc-link-search=native=/usr/local/lib");
        println!("cargo:rustc-link-lib=static=blis");

        //Needed when BLIS is compiled with GCC and OpenMP:
        println!("cargo:rustc-link-search=native=/usr/lib/gcc/x86_64-linux-gnu/5");
        println!("cargo:rustc-link-lib=dylib=gomp");

        //Use bindgen to create bindings to BLIS's typedefs
        //This allows us to interface with the BLIS micro-kernel
		let bindings = bindgen::Builder::default()
			.header("blis_types_wrapper.h")
            .clang_arg("-include")
            .clang_arg("stddef.h")
            .clang_arg(format!("-I/{}/blis/include/blis", std::env::home_dir().unwrap().to_str().unwrap()))
			.generate()
			.expect("Unable to generate bindings");

        // Write the bindings to the $OUT_DIR/bindings.rs file.
    	let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
    	bindings
			.write_to_file(out_path.join("bindings.rs"))
			.expect("Couldn't write bindings!");

        //Needed for linking with BLIS when it was compiled with icc
        /*
        println!("cargo:rustc-link-lib=static=irc");
        */
    }

    if cfg!(feature="libxsmm"){
        println!("cargo:rustc-link-search=native={}/libxsmm/lib", std::env::home_dir().unwrap().to_str().unwrap() );
        println!("cargo:rustc-link-lib=static=xsmm");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Adam Perry <adam.n.perry@gmail.com>
//
// This software may be modified and distributed under the terms of the MIT license.  See the
// LICENSE file for details.

use std::fs::copy;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env!("OUT_DIR");

    // configure the build
    Command::new("./configure")
        .arg("--enable-shared")
        .arg("--with-pic")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to configure parasail.");

    // build the library
    Command::new("make")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to build parasail.");

    // put the static library in the right directory so we can clean up
    let target_file = format!("{}/libparasail.a", out_dir);
    copy("parasail_c/.libs/libparasail.a", target_file)
        .expect("Problem copying library to target directoy.");

    // clean up the temporary build files
    Command::new("make")
        .current_dir(Path::new("parasail_c"))
        .arg("clean")
        .output()
        .expect("Failed to clean up build files.");

    // clean up the configuration files
    Command::new("make")
        .arg("distclean")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to clean up configuration files.");

    // let cargo know that it can find the file in the out directory
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=parasail");
}
<commit_msg>Experimenting with parallel builds.<commit_after>// Copyright (c) 2016 Adam Perry <adam.n.perry@gmail.com>
//
// This software may be modified and distributed under the terms of the MIT license.  See the
// LICENSE file for details.

use std::env;
use std::fs::copy;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env!("OUT_DIR");
    let num_jobs = env::var("NUM_JOBS").unwrap_or("1".to_string());

    // configure the build
    Command::new("./configure")
        .arg("--enable-shared")
        .arg("--with-pic")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to configure parasail.");

    // build the library
    Command::new("make")
        .arg(format!("-j{}", num_jobs))
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to build parasail.");

    // put the static library in the right directory so we can clean up
    let target_file = format!("{}/libparasail.a", out_dir);
    copy("parasail_c/.libs/libparasail.a", target_file)
        .expect("Problem copying library to target directoy.");

    // clean up the temporary build files
    Command::new("make")
        .current_dir(Path::new("parasail_c"))
        .arg("clean")
        .output()
        .expect("Failed to clean up build files.");

    // clean up the configuration files
    Command::new("make")
        .arg("distclean")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to clean up configuration files.");

    // let cargo know that it can find the file in the out directory
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=parasail");
}
<|endoftext|>


<commit_before>// build.rs

extern crate pkg_config;
extern crate bindgen;
extern crate cmake;
extern crate cc;

use std::env;
use std::path::Path;

use std::fs::{self, File};
use std::io::Write;

fn format_write(builder: bindgen::Builder, output: &str) {
    let s = builder
        .generate()
        .unwrap()
        .to_string()
        .replace("/**", "/*")
        .replace("/*!", "/*");

    let mut file = File::create(output).unwrap();

    let _ = file.write(s.as_bytes());
}

fn main() {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_AV1_ENCODER", "0")
        .define("CONFIG_DEBUG", "1")
        .define("CONFIG_EXPERIMENTAL", "1")
        .define("CONFIG_UNIT_TESTS", "0")
        .define("CONFIG_EXT_PARTITION", "0")
        .define("CONFIG_EXT_PARTITION_TYPES", "0")
        .define("CONFIG_OBU", "0")
        .define("CONFIG_FILTER_INTRA", "0")
        .define("CONFIG_EXT_SKIP", "0")
        .define("CONFIG_LV_MAP", "1")
        .define("CONFIG_ANALYZER", "0")
        .define("CONFIG_Q_ADAPT_PROBS", "0")
        .define("AOM_TARGET_CPU", "generic")
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));

    let libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();
    let headers = libs.include_paths.clone();

    let mut builder = bindgen::builder()
        .raw_line("#![allow(dead_code)]")
        .raw_line("#![allow(non_camel_case_types)]")
        .raw_line("#![allow(non_snake_case)]")
        .raw_line("#![allow(non_upper_case_globals)]")
        .blacklist_type("max_align_t")
        .rustfmt_bindings(false)
        .header("data/aom.h");

    for header in headers {
        builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
    }

    // Manually fix the comment so rustdoc won't try to pick them
    format_write(builder, "tests/aom.rs");

    println!("cargo:rerun-if-changed=aom_build/aom/");

    cc::Build::new()
        .file("aom_build/aom/aom_dsp/fwd_txfm.c")
        .file("aom_build/aom/av1/encoder/dct.c")
        .include("aom_build")
        .include("aom_build/aom")
        .flag("-std=c99")
        .compile("libntr.a");
}
<commit_msg>Rebuild if the aom_build contents changed<commit_after>// build.rs

extern crate pkg_config;
extern crate bindgen;
extern crate cmake;
extern crate cc;

use std::env;
use std::path::Path;

use std::fs::{self, File};
use std::io::Write;

fn format_write(builder: bindgen::Builder, output: &str) {
    let s = builder
        .generate()
        .unwrap()
        .to_string()
        .replace("/**", "/*")
        .replace("/*!", "/*");

    let mut file = File::create(output).unwrap();

    let _ = file.write(s.as_bytes());
}

fn main() {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_AV1_ENCODER", "0")
        .define("CONFIG_DEBUG", "1")
        .define("CONFIG_EXPERIMENTAL", "1")
        .define("CONFIG_UNIT_TESTS", "0")
        .define("CONFIG_EXT_PARTITION", "0")
        .define("CONFIG_EXT_PARTITION_TYPES", "0")
        .define("CONFIG_OBU", "0")
        .define("CONFIG_FILTER_INTRA", "0")
        .define("CONFIG_EXT_SKIP", "0")
        .define("CONFIG_LV_MAP", "1")
        .define("CONFIG_ANALYZER", "0")
        .define("CONFIG_Q_ADAPT_PROBS", "0")
        .define("AOM_TARGET_CPU", "generic")
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));

    let libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();
    let headers = libs.include_paths.clone();

    let mut builder = bindgen::builder()
        .raw_line("#![allow(dead_code)]")
        .raw_line("#![allow(non_camel_case_types)]")
        .raw_line("#![allow(non_snake_case)]")
        .raw_line("#![allow(non_upper_case_globals)]")
        .blacklist_type("max_align_t")
        .rustfmt_bindings(false)
        .header("data/aom.h");

    for header in headers {
        builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
    }

    // Manually fix the comment so rustdoc won't try to pick them
    format_write(builder, "tests/aom.rs");

    {
        use std::fs;
        fn rerun_dir<P: AsRef<Path>>(dir: P) {
            for entry in fs::read_dir(dir).unwrap() {
                let entry = entry.unwrap();
                let path = entry.path();
                println!("cargo:rerun-if-changed={}", path.to_string_lossy());

                if path.is_dir() {
                    rerun_dir(path);
                }
            }
        }

        rerun_dir("aom_build");
    }

    cc::Build::new()
        .file("aom_build/aom/aom_dsp/fwd_txfm.c")
        .file("aom_build/aom/av1/encoder/dct.c")
        .include("aom_build")
        .include("aom_build/aom")
        .flag("-std=c99")
        .compile("libntr.a");
}
<|endoftext|>