diff options
author | Alex Crichton <alex@alexcrichton.com> | 2015-04-30 10:51:59 -0700 |
---|---|---|
committer | Alex Crichton <alex@alexcrichton.com> | 2015-04-30 17:48:28 -0700 |
commit | d8a78b354043942dd06bec6c5955e7e89306eeac (patch) | |
tree | 3e8b8947ad8720cf3541dc4d6807ad4460d75cb0 | |
parent | 168b9baa572c1f5cd047eb322a10691379a7a55f (diff) | |
download | ssh2-rs-d8a78b354043942dd06bec6c5955e7e89306eeac.zip |
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.
-rw-r--r-- | appveyor.yml | 9 | ||||
-rw-r--r-- | libssh2-sys/build.rs | 126 |
2 files changed, 64 insertions, 71 deletions
diff --git a/appveyor.yml b/appveyor.yml index 21bea1f..83626be 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,20 @@ install: + # libssh2 depends on libbcrypt, but apparently this library is not available + # in the normal MinGW distribution (installed on bots by default), so we + # install our own custom mingw-w64 compiler - ps: | if (!(Test-Path 'x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z')) { Start-FileDownload 'http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z' } - 7z x x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z > nul - set PATH=%PATH%;C:\projects\ssh2-rs\mingw64\bin + + # Our build script currently relies on `make`, so be sure that it's in the PATH - set PATH=%PATH%;C:\MinGW\msys\1.0\bin + + # Download a 64-bit compiler (matching the 64-bit mingw-w64 compiler being + # used), and currently also use a beta (there's a bug in nightly for executing + # commands). - ps: | if (!(Test-Path 'rust-1.0.0-beta-x86_64-pc-windows-gnu.exe')) { Start-FileDownload 'https://static.rust-lang.org/dist/rust-1.0.0-beta-x86_64-pc-windows-gnu.exe' 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<PathBuf> { - 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); + } } |