| 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() |
| } |