blob: 5f0282440c335a5515886b76b1d8119564412a3c [file] [log] [blame] [edit]
extern crate cc;
extern crate pkg_config;
#[cfg(target_env = "msvc")]
extern crate vcpkg;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok();
if !zlib_ng_compat && try_vcpkg() {
return;
}
// The system copy of libssh2 is not used by default because it
// can lead to having two copies of libssl loaded at once.
// See https://github.com/alexcrichton/ssh2-rs/pull/88
println!("cargo:rerun-if-env-changed=LIBSSH2_SYS_USE_PKG_CONFIG");
if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() {
if zlib_ng_compat {
panic!("LIBSSH2_SYS_USE_PKG_CONFIG set, but cannot use zlib-ng-compat with system libssh2");
}
if let Ok(lib) = pkg_config::find_library("libssh2") {
for path in &lib.include_paths {
println!("cargo:include={}", path.display());
}
return;
}
}
if !Path::new("libssh2/.git").exists() {
let _ = Command::new("git")
.args(&["submodule", "update", "--init"])
.status();
}
let target = env::var("TARGET").unwrap();
let profile = env::var("PROFILE").unwrap();
let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let mut cfg = cc::Build::new();
let include = dst.join("include");
println!("cargo:include={}", include.display());
println!("cargo:root={}", dst.display());
let build = dst.join("build");
cfg.out_dir(&build);
fs::create_dir_all(&build).unwrap();
fs::create_dir_all(&include).unwrap();
fs::copy("libssh2/include/libssh2.h", include.join("libssh2.h")).unwrap();
fs::copy(
"libssh2/include/libssh2_publickey.h",
include.join("libssh2_publickey.h"),
)
.unwrap();
fs::copy(
"libssh2/include/libssh2_sftp.h",
include.join("libssh2_sftp.h"),
)
.unwrap();
cfg.file("libssh2/src/agent.c")
.file("libssh2/src/bcrypt_pbkdf.c")
.file("libssh2/src/blowfish.c")
.file("libssh2/src/channel.c")
.file("libssh2/src/comp.c")
.file("libssh2/src/crypt.c")
.file("libssh2/src/global.c")
.file("libssh2/src/hostkey.c")
.file("libssh2/src/keepalive.c")
.file("libssh2/src/kex.c")
.file("libssh2/src/knownhost.c")
.file("libssh2/src/mac.c")
.file("libssh2/src/misc.c")
.file("libssh2/src/packet.c")
.file("libssh2/src/pem.c")
.file("libssh2/src/publickey.c")
.file("libssh2/src/scp.c")
.file("libssh2/src/session.c")
.file("libssh2/src/sftp.c")
.file("libssh2/src/transport.c")
.file("libssh2/src/userauth.c")
.file("libssh2/src/userauth_kbd_packet.c")
.include(&include)
.include("libssh2/src");
cfg.define("HAVE_LONGLONG", None);
if target.contains("windows") {
cfg.include("libssh2/win32");
cfg.define("LIBSSH2_WIN32", None);
cfg.file("libssh2/src/agent_win.c");
if env::var_os("CARGO_FEATURE_OPENSSL_ON_WIN32").is_some() {
cfg.define("LIBSSH2_OPENSSL", None);
cfg.define("HAVE_EVP_AES_128_CTR", None);
cfg.file("libssh2/src/openssl.c");
println!("cargo:rustc-link-lib=static=libssl");
println!("cargo:rustc-link-lib=static=libcrypto");
} else {
cfg.define("LIBSSH2_WINCNG", None);
cfg.file("libssh2/src/wincng.c");
}
} else {
cfg.flag("-fvisibility=hidden");
cfg.define("HAVE_SNPRINTF", None);
cfg.define("HAVE_UNISTD_H", None);
cfg.define("HAVE_INTTYPES_H", None);
cfg.define("HAVE_STDLIB_H", None);
cfg.define("HAVE_SYS_SELECT_H", None);
cfg.define("HAVE_SYS_SOCKET_H", None);
cfg.define("HAVE_SYS_IOCTL_H", None);
cfg.define("HAVE_SYS_TIME_H", None);
cfg.define("HAVE_SYS_UN_H", None);
cfg.define("HAVE_O_NONBLOCK", None);
cfg.define("LIBSSH2_OPENSSL", None);
cfg.define("HAVE_LIBCRYPT32", None);
cfg.define("HAVE_EVP_AES_128_CTR", None);
cfg.define("HAVE_POLL", None);
cfg.define("HAVE_GETTIMEOFDAY", None);
cfg.file("libssh2/src/openssl.c");
// Create `libssh2_config.h`
let config = fs::read_to_string("libssh2/src/libssh2_config_cmake.h.in").unwrap();
let config = config
.lines()
.filter(|l| !l.contains("#cmakedefine"))
.collect::<Vec<_>>()
.join("\n");
fs::write(build.join("libssh2_config.h"), &config).unwrap();
cfg.include(&build);
}
/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
cfg.define("LIBSSH2_DH_GEX_NEW", None);
cfg.define("LIBSSH2_HAVE_ZLIB", None);
if profile.contains("debug") {
cfg.define("LIBSSH2DEBUG", None);
}
println!("cargo:rerun-if-env-changed=DEP_Z_INCLUDE");
if let Some(path) = env::var_os("DEP_Z_INCLUDE") {
cfg.include(path);
}
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_INCLUDE");
if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") {
if let Some(path) = env::split_paths(&path).next() {
if let Some(path) = path.to_str() {
if path.len() > 0 {
cfg.include(path);
}
}
}
}
let libssh2h = fs::read_to_string("libssh2/include/libssh2.h").unwrap();
let version_line = libssh2h
.lines()
.find(|l| l.contains("LIBSSH2_VERSION"))
.unwrap();
let version = &version_line[version_line.find('"').unwrap() + 1..version_line.len() - 1];
let pkgconfig = dst.join("lib/pkgconfig");
fs::create_dir_all(&pkgconfig).unwrap();
fs::write(
pkgconfig.join("libssh2.pc"),
fs::read_to_string("libssh2/libssh2.pc.in")
.unwrap()
.replace("@prefix@", dst.to_str().unwrap())
.replace("@exec_prefix@", "")
.replace("@libdir@", dst.join("lib").to_str().unwrap())
.replace("@includedir@", include.to_str().unwrap())
.replace("@LIBS@", "")
.replace("@LIBSREQUIRED@", "")
.replace("@LIBSSH2VER@", version),
)
.unwrap();
cfg.warnings(false);
cfg.compile("ssh2");
if target.contains("windows") {
println!("cargo:rustc-link-lib=bcrypt");
println!("cargo:rustc-link-lib=crypt32");
println!("cargo:rustc-link-lib=user32");
println!("cargo:rustc-link-lib=ntdll");
}
}
#[cfg(not(target_env = "msvc"))]
fn try_vcpkg() -> bool {
false
}
#[cfg(target_env = "msvc")]
fn try_vcpkg() -> bool {
vcpkg::Config::new()
.emit_includes(true)
.probe("libssh2")
.map(|_| {
// found libssh2 which depends on openssl and zlib
vcpkg::Config::new()
.lib_name("libssl")
.lib_name("libcrypto")
.probe("openssl")
.or_else(|_| {
// openssl 1.1 was not found, try openssl 1.0
vcpkg::Config::new()
.lib_name("libeay32")
.lib_name("ssleay32")
.probe("openssl")
})
.expect(
"configured libssh2 from vcpkg but could not \
find openssl libraries that it depends on",
);
vcpkg::Config::new()
.lib_names("zlib", "zlib1")
.probe("zlib")
.expect(
"configured libssh2 from vcpkg but could not \
find the zlib library that it depends on",
);
println!("cargo:rustc-link-lib=crypt32");
println!("cargo:rustc-link-lib=gdi32");
println!("cargo:rustc-link-lib=user32");
})
.is_ok()
}