extern crate gcc;
use std::fs;
use std::io;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsString;
trait CommandExt {
fn execute(&mut self) -> io::Result<()>;
}
impl CommandExt for Command {
fn execute(&mut self) -> io::Result<()> {
let status = try!(self.status());
if status.success() {
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, format!("The command\n\
\t{:?}\n\
did not run successfully.", self)))
}
}
}
fn build_lua(tooling: &gcc::Tool, dir: &Path) -> io::Result<()> {
let platform = match env::var("TARGET").unwrap().split('-').nth(2).unwrap() {
"windows" => "mingw",
"macos" => "macosx",
"linux" => "linux",
"freebsd" => "freebsd",
"dragonfly" => "bsd",
_ => "generic",
};
let mut cc = OsString::from("CC=");
cc.push(tooling.path());
let mut cflags = OsString::from("MYCFLAGS=");
for arg in tooling.args() {
cflags.push(arg);
cflags.push(" ");
}
let mut command = Command::new("make");
for &(ref key, ref val) in tooling.env() {
command.env(key, val);
}
command.current_dir(dir)
.arg(platform)
.arg(cc)
.arg(cflags)
.execute()
}
#[cfg(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "macos")))]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
Command::new("wget").arg(url).current_dir(cwd).execute()
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
Command::new("fetch").arg(url).current_dir(cwd).execute()
}
#[cfg(target_os = "macos")]
fn fetch_in_dir(url: &str, cwd: &Path) -> io::Result<()> {
Command::new("curl").arg("-O").arg(url).current_dir(cwd).execute()
}
fn prebuild() -> io::Result<()> {
let lua_version = match env::var_os("LUA_VERSION") {
Some(lua_version) => lua_version,
None => From::from("5.3.3"),
};
let lua_version = lua_version.to_str().unwrap();
let lua_dir = format!("lua-{}", lua_version);
let lua_tarball = format!("{}.tar.gz", lua_dir);
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let tooling = gcc::Config::new().get_compiler();
if !fs::metadata(build_dir.join(&format!("{}/src/liblua.a", lua_dir))).is_ok() {
try!(fs::create_dir_all(&build_dir));
if !fs::metadata(build_dir.join(&lua_tarball)).is_ok() {
match env::var_os("LUA_LOCAL_SOURCE") {
Some(lua_source_path) => {
try!(Command::new("cp")
.arg(&PathBuf::from(lua_source_path).join(&lua_tarball))
.arg(".")
.current_dir(&build_dir)
.execute());
}
None => {
try!(fetch_in_dir(&format!(
"http://www.lua.org/ftp/{}", lua_tarball), &build_dir));
}
}
try!(Command::new("tar")
.arg("xzf")
.arg(&lua_tarball)
.current_dir(&build_dir)
.execute());
}
try!(build_lua(&tooling, &build_dir.join(&lua_dir)));
}
if !fs::metadata(build_dir.join("glue.rs")).is_ok() {
let glue = build_dir.join("glue");
try!(Command::new("gcc")
.arg("-I").arg(build_dir.join(&format!("{}/src", lua_dir)))
.arg("src/glue/glue.c")
.arg("-o").arg(&glue)
.execute());
try!(Command::new(glue)
.arg(build_dir.join("glue.rs"))
.execute());
}
println!("cargo:rustc-link-lib=static=lua");
println!("cargo:rustc-link-search=native={}/{}/src", build_dir.to_str().unwrap(), lua_dir);
Ok(())
}
fn main() {
match prebuild() {
Err(e) => panic!("Error: {}", e),
Ok(()) => (),
}
}