From d8a78b354043942dd06bec6c5955e7e89306eeac Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 30 Apr 2015 10:51:59 -0700 Subject: Overhaul the build on windows * Have an entirely separate path for windows builds * Run `make install` on unix builds for libssh2 * On Windows, first detect whether `make` is available * Use the specific `win32/GNUmakefile` for windows instead of the standard configure/make procedure for unix. * Continue doing a manual install on Windows, but don't rely on `pkg-config` existing and don't emit a pkg-config file. One day this may support MSVC-based builds, but support is not added at this time. --- libssh2-sys/build.rs | 126 ++++++++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 71 deletions(-) (limited to 'libssh2-sys/build.rs') diff --git a/libssh2-sys/build.rs b/libssh2-sys/build.rs index 20b6a4f..1ce4387 100644 --- a/libssh2-sys/build.rs +++ b/libssh2-sys/build.rs @@ -21,7 +21,7 @@ fn main() { let mut cflags = env::var("CFLAGS").unwrap_or(String::new()); let target = env::var("TARGET").unwrap(); - let windows = target.contains("windows") || target.contains("mingw"); + let windows = target.contains("windows"); cflags.push_str(" -ffunction-sections -fdata-sections"); if target.contains("i686") { @@ -41,76 +41,64 @@ fn main() { Err(..) => {} } - let src = PathBuf::from(&env::var_os("CARGO_MANIFEST_DIR").unwrap()); let dst = PathBuf::from(&env::var_os("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 root = t!(env::current_dir()).join("libssh2-1.5.0"); let _ = fs::remove_dir_all(&dst.join("include")); - let _ = fs::remove_dir_all(&dst.join("lib")); - let _ = fs::remove_dir_all(&dst.join("build")); - t!(fs::create_dir(&dst.join("build"))); - - let root = src.join("libssh2-1.5.0"); - // 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?! - run(Command::new("sh") - .env("CFLAGS", &cflags) - .env("LD", &which("ld").unwrap()) - .current_dir(&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{}", env::var("NUM_JOBS").unwrap())) - .current_dir(&dst.join("build/src"))); - - // Don't run `make install` because apparently it's a little buggy on mingw - // for windows. - t!(fs::create_dir_all(&dst.join("lib/pkgconfig"))); - - // 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 fs::metadata(&p1).is_ok() { - t!(fs::copy(&p1, &dst.join("lib/libssh2.a"))); + let _ = fs::remove_dir_all(dst.join("lib")); + let _ = fs::remove_dir_all(dst.join("build")); + t!(fs::create_dir(dst.join("build"))); + + if !windows { + run(Command::new(root.join("configure")) + .env("CFLAGS", &cflags) + .current_dir(dst.join("build")) + .arg("--enable-shared=no") + .arg("--disable-examples-build") + .arg(format!("--prefix={}", dst.display()))); + run(Command::new(&make()) + .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap())) + .current_dir(dst.join("build/src"))); + run(Command::new(&make()) + .arg("install") + .current_dir(dst.join("build"))); + + // Unfortunately the pkg-config file generated for libssh2 indicates + // that it depends on zlib, but most systems don't actually have a + // zlib.pc, so pkg-config will say that libssh2 doesn't exist. We + // generally take care of the zlib dependency elsewhere, so we just + // remove that part from the pkg-config file + let mut pc = String::new(); + let pkgconfig = dst.join("lib/pkgconfig/libssh2.pc"); + t!(t!(File::open(&pkgconfig)).read_to_string(&mut pc)); + let pc = pc.replace(",zlib", ""); + let bytes = pc.as_bytes(); + t!(t!(File::create(pkgconfig)).write_all(bytes)); + } else { - t!(fs::copy(&p2, &dst.join("lib/libssh2.a"))); - } + t!(fs::create_dir(dst.join("lib"))); + + if Command::new("make").arg("-v").output().is_ok() { + run(Command::new("make") + .current_dir(root.join("win32")) + .arg("-fGNUmakefile") + .arg("WITH_WINCNG=1") + .arg("WITH_ZLIB=1") + .arg("lib")); + t!(fs::remove_dir_all(root.join("win32/release"))); + t!(fs::copy(root.join("win32/libssh2.a"), dst.join("lib/libssh2.a"))); + t!(fs::remove_file(root.join("win32/libssh2.a"))); + } else { + panic!("\n\ncurrently need `make` installed on windows\n"); + } - // Unfortunately the pkg-config file generated for libssh2 indicates that it - // depends on zlib, but most systems don't actually have a zlib.pc, so - // pkg-config will say that libssh2 doesn't exist. We generally take care of - // the zlib dependency elsewhere, so we just remove that part from the - // pkg-config file - let mut pc = String::new(); - t!(t!(File::open(dst.join("build/libssh2.pc"))).read_to_string(&mut pc)); - let pc = pc.replace(",zlib", "").replace("zlib", ""); - let bytes = pc.as_bytes(); - t!(t!(File::create(dst.join("lib/pkgconfig/libssh2.pc"))).write_all(bytes)); - - { let root = root.join("include"); let dst = dst.join("include"); t!(fs::create_dir_all(&dst)); - t!(fs::copy(&root.join("libssh2.h"), &dst.join("libssh2.h"))); - t!(fs::copy(&root.join("libssh2_publickey.h"), - &dst.join("libssh2_publickey.h"))); - t!(fs::copy(&root.join("libssh2_sftp.h"), &dst.join("libssh2_sftp.h"))); + t!(fs::copy(root.join("libssh2.h"), dst.join("libssh2.h"))); + t!(fs::copy(root.join("libssh2_publickey.h"), + dst.join("libssh2_publickey.h"))); + t!(fs::copy(root.join("libssh2_sftp.h"), dst.join("libssh2_sftp.h"))); } if windows { @@ -130,12 +118,8 @@ fn make() -> &'static str { fn run(cmd: &mut Command) { println!("running: {:?}", cmd); - assert!(t!(cmd.status()).success()); -} - -fn which(cmd: &str) -> Option { - let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX); - env::split_paths(&env::var("PATH").unwrap()).map(|p| { - p.join(&cmd) - }).find(|p| fs::metadata(p).is_ok()) + let status = t!(cmd.status()); + if !status.success() { + panic!("command did not succeed, exited with: {}", status); + } } -- cgit v1.2.3