summaryrefslogtreecommitdiff
path: root/libssh2-sys/build.rs
blob: d6d2344c0fda946cfe6b53f585f696e9d2af0cb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
extern crate "pkg-config" as pkg_config;

use std::os;
use std::io::{mod, fs, Command};
use std::io::process::InheritFd;
use std::io::fs::PathExtensions;

fn main() {
    match pkg_config::find_library("libssh2") {
        Ok(()) => return,
        Err(..) => {}
    }

    let mut cflags = os::getenv("CFLAGS").unwrap_or(String::new());
    let target = os::getenv("TARGET").unwrap();
    let windows = target.contains("windows") || target.contains("mingw");
    cflags.push_str(" -ffunction-sections -fdata-sections");

    if target.contains("i686") {
        cflags.push_str(" -m32");
    } else if target.as_slice().contains("x86_64") {
        cflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cflags.push_str(" -fPIC");
    }

    match os::getenv("DEP_OPENSSL_ROOT") {
        Some(s) => {
            cflags.push_str(format!(" -I{}/include", s).as_slice());
            cflags.push_str(format!(" -L{}/lib", s).as_slice());
        }
        None => {}
    }

    let src = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let dst = Path::new(os::getenv("OUT_DIR").unwrap());

    let mut config_opts = Vec::new();
    if windows {
        config_opts.push("--without-openssl".to_string());
        config_opts.push("--with-wincng".to_string());
    }
    config_opts.push("--enable-shared=no".to_string());
    config_opts.push("--disable-examples-build".to_string());
    config_opts.push(format!("--prefix={}", dst.display()));

    let _ = fs::rmdir_recursive(&dst.join("include"));
    let _ = fs::rmdir_recursive(&dst.join("lib"));
    let _ = fs::rmdir_recursive(&dst.join("build"));
    fs::mkdir(&dst.join("build"), io::USER_DIR).unwrap();

    let root = src.join("libssh2-1.4.4-20140901");
    // 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...
    run(Command::new("sh")
                .env("CFLAGS", cflags)
                .cwd(&dst.join("build"))
                .arg("-c")
                .arg(format!("{} {}", root.join("configure").display(),
                             config_opts.connect(" "))
                            .replace("C:\\", "/c/")
                            .replace("\\", "/")));
    run(Command::new(make())
                .arg(format!("-j{}", os::getenv("NUM_JOBS").unwrap()))
                .cwd(&dst.join("build/src")));

    // Don't run `make install` because apparently it's a little buggy on mingw
    // for windows.
    fs::mkdir_recursive(&dst.join("lib/pkgconfig"), io::USER_DIR).unwrap();

    // Which one does windows generate? Who knows!
    let p1 = dst.join("build/src/.libs/libssh2.a");
    let p2 = dst.join("build/src/.libs/libssh2.lib");
    if p1.exists() {
        fs::rename(&p1, &dst.join("lib/libssh2.a")).unwrap();
    } else {
        fs::rename(&p2, &dst.join("lib/libssh2.a")).unwrap();
    }
    fs::rename(&dst.join("build/libssh2.pc"),
               &dst.join("lib/pkgconfig/libssh2.pc")).unwrap();

    {
        let root = root.join("include");
        let dst = dst.join("include");
        for file in fs::walk_dir(&root).unwrap() {
            if fs::stat(&file).unwrap().kind != io::TypeFile { continue }

            let part = file.path_relative_from(&root).unwrap();
            let dst = dst.join(part);
            fs::mkdir_recursive(&dst.dir_path(), io::USER_DIR).unwrap();
            fs::copy(&file, &dst).unwrap();
        }
    }

    if windows {
        println!("cargo:rustc-flags=-l ws2_32 -l bcrypt -l crypt32");
    }
    println!("cargo:rustc-flags=-L {}/lib -l ssh2:static", dst.display());
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
}

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

fn run(cmd: &mut Command) {
    println!("running: {}", cmd);
    assert!(cmd.stdout(InheritFd(1))
               .stderr(InheritFd(2))
               .status()
               .unwrap()
               .success());

}