use std::path::PathBuf;
fn main() {
if std::env::var_os("CARGO_FEATURE_VENDORED").is_none()
&& pkg_config::Config::new()
.atleast_version("0.9.7")
.probe("libssh")
.is_ok()
{
return;
}
let mut cfg = cc::Build::new();
cfg.define("LIBSSH_STATIC", None);
cfg.define("_GNU_SOURCE", None);
cfg.include("vendored/include");
let dst = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
let include = dst.join("include");
std::fs::create_dir_all(&include).unwrap();
cfg.include(&include);
println!("cargo:include={}", include.display());
println!("cargo:root={}", dst.display());
let openssl_version = std::env::var("DEP_OPENSSL_VERSION_NUMBER").unwrap();
let openssl_version = u64::from_str_radix(&openssl_version, 16).unwrap();
let target = std::env::var("TARGET").unwrap();
cfg.define("GLOBAL_CLIENT_CONFIG", Some("\"/etc/ssh/ssh_config\""));
cfg.define("HAVE_GETADDRINFO", Some("1"));
cfg.define("HAVE_LIBCRYPTO", Some("1"));
cfg.define("HAVE_OPENSSL_AES_H", Some("1"));
cfg.define("HAVE_OPENSSL_BLOWFISH_H", Some("1"));
cfg.define("HAVE_OPENSSL_DES_H", Some("1"));
cfg.define("HAVE_OPENSSL_ECC", Some("1"));
cfg.define("HAVE_OPENSSL_ECDH_H", Some("1"));
cfg.define("HAVE_OPENSSL_ECDSA_H", Some("1"));
cfg.define("HAVE_ECC", Some("1"));
cfg.define("HAVE_DSA", Some("1"));
cfg.define("HAVE_OPENSSL_EC_H", Some("1"));
if openssl_version >= 0x1_01_01_00_0 {
cfg.define("HAVE_OPENSSL_EVP_CHACHA20", Some("1"));
}
if openssl_version < 0x1_01_00_00_0 {
cfg.file("vendored/src/libcrypto-compat.c");
}
if false && openssl_version >= 0x3_00_00_00_0 {
cfg.define("HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID", Some("1"));
}
cfg.define("HAVE_STDINT_H", Some("1"));
cfg.define("WITH_ZLIB", Some("1"));
cfg.define("WITH_GEX", Some("1"));
cfg.define("WITH_SFTP", Some("1"));
if target.contains("windows") {
cfg.define("HAVE_IO_H", Some("1"));
cfg.define("HAVE_SECURE_ZERO_MEMORY", Some("1"));
cfg.define("HAVE__SNPRINTF", Some("1"));
cfg.define("HAVE__SNPRINTF_S", Some("1"));
cfg.define("HAVE__STRTOUI64", Some("1"));
cfg.define("HAVE__VSNPRINTF", Some("1"));
cfg.define("HAVE__VSNPRINTF_S", Some("1"));
cfg.define("HAVE_ISBLANK", Some("1"));
} else {
cfg.define("HAVE_ARPA_INET_H", Some("1"));
cfg.define("HAVE_CLOCK_GETTIME", Some("1"));
cfg.define("HAVE_PTHREAD_H", Some("1"));
cfg.define("HAVE_PTHREAD", Some("1"));
cfg.define("HAVE_SELECT", Some("1"));
cfg.define("HAVE_SNPRINTF", Some("1"));
cfg.define("HAVE_STRTOULL", Some("1"));
cfg.define("HAVE_SYS_TIME_H", Some("1"));
cfg.define("HAVE_TERMIOS_H", Some("1"));
cfg.define("HAVE_UNISTD_H", Some("1"));
cfg.define("HAVE_VSNPRINTF", Some("1"));
if !target.contains("darwin") {
cfg.define("HAVE_POLL", Some("1"));
}
}
if target.contains("linux") {
cfg.define("HAVE_STRNDUP", Some("1"));
}
if target.contains("darwin") {
cfg.define("HAVE_NTOHLL", Some("1"));
cfg.define("HAVE_HTONLL", Some("1"));
}
let compiler = cfg.get_compiler();
if compiler.is_like_gnu() || compiler.is_like_clang() {
cfg.define("HAVE_COMPILER__FUNCTION__", Some("1"));
cfg.define("HAVE_COMPILER__FUNC__", Some("1"));
cfg.define("HAVE_GCC_THREAD_LOCAL_STORAGE", Some("1"));
}
if compiler.is_like_msvc() {
cfg.define("HAVE_COMPILER__FUNC__", Some("1"));
cfg.define("HAVE_MSC_THREAD_LOCAL_STORAGE", Some("1"));
}
std::fs::write(include.join("config.h"), "// nothing").unwrap();
let version = std::fs::read_to_string("vendored/include/libssh/libssh_version.h.cmake")
.unwrap()
.replace("@libssh_VERSION_MAJOR@", "0")
.replace("@libssh_VERSION_MINOR@", "8")
.replace("@libssh_VERSION_PATCH@", "90");
std::fs::create_dir_all(include.join("libssh")).unwrap();
std::fs::write(include.join("libssh/libssh_version.h"), version).unwrap();
println!("cargo:rerun-if-env-changed=DEP_Z_INCLUDE");
if let Some(path) = std::env::var_os("DEP_Z_INCLUDE") {
cfg.include(path);
}
if let Some(zlib_root) = std::env::var_os("DEP_Z_ROOT") {
println!(
"cargo:rustc-link-search=native={}",
PathBuf::from(zlib_root).join("lib").to_str().unwrap()
);
}
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_INCLUDE");
if let Some(path) = std::env::var_os("DEP_OPENSSL_INCLUDE") {
if let Some(path) = std::env::split_paths(&path).next() {
if let Some(path) = path.to_str() {
if !path.is_empty() {
cfg.include(path);
}
}
}
}
if let Some(zlib_root) = std::env::var_os("DEP_OPENSSL_ROOT") {
println!(
"cargo:rustc-link-search=native={}",
PathBuf::from(zlib_root).join("lib").to_str().unwrap()
);
}
if false {
for (k, v) in std::env::vars() {
if k.starts_with("CARGO") || k.starts_with("DEP") {
eprintln!("{}={}", k, v);
}
}
panic!("boo");
}
cfg.warnings(false);
for f in &[
"agent.c",
"auth.c",
"base64.c",
"bignum.c",
"buffer.c",
"callbacks.c",
"chachapoly.c",
"channels.c",
"client.c",
"config.c",
"config_parser.c",
"connect.c",
"connector.c",
"crypto_common.c",
"curve25519.c",
"dh-gex.c",
"dh.c",
"dh_crypto.c",
"ecdh.c",
"ecdh_crypto.c",
"error.c",
"external/bcrypt_pbkdf.c",
"external/blowfish.c",
"external/chacha.c",
"external/curve25519_ref.c",
"external/ed25519.c",
"external/fe25519.c",
"external/ge25519.c",
"external/poly1305.c",
"external/sc25519.c",
"getpass.c",
"gzip.c",
"init.c",
"kdf.c",
"kex.c",
"known_hosts.c",
"knownhosts.c",
"legacy.c",
"libcrypto.c",
"log.c",
"match.c",
"messages.c",
"misc.c",
"options.c",
"packet.c",
"packet_cb.c",
"packet_crypt.c",
"pcap.c",
"pki.c",
"pki_container_openssh.c",
"pki_crypto.c",
"pki_ed25519.c",
"pki_ed25519_common.c",
"poll.c",
"sftp.c",
"scp.c",
"session.c",
"socket.c",
"string.c",
"threads.c",
"threads/libcrypto.c",
"threads/noop.c",
"token.c",
"wrapper.c",
] {
cfg.file(&format!("vendored/src/{}", f));
}
if cfg!(unix) {
cfg.file("vendored/src/threads/pthread.c");
}
if cfg!(windows) {
cfg.file("vendored/src/threads/winlocks.c");
}
cfg.compile("libssh");
if target.contains("windows") {
println!("cargo:rustc-link-lib=libcrypto");
println!("cargo:rustc-link-lib=libssl");
println!("cargo:rustc-link-lib=crypt32");
println!("cargo:rustc-link-lib=user32");
println!("cargo:rustc-link-lib=shell32");
println!("cargo:rustc-link-lib=ntdll");
} else {
println!("cargo:rustc-link-lib=ssl");
println!("cargo:rustc-link-lib=crypto");
}
println!("cargo:rustc-link-lib=z");
}