#![allow(dead_code)]
#![allow(unreachable_code)]
use std::fs; use std::path::{PathBuf, Path};
extern crate cc;
#[cfg(feature = "link_shared_librosie")]
extern crate pkg_config;
fn main() -> Result<(), i32> {
#[cfg(all(feature = "link_shared_librosie", feature = "build_static_librosie"))]
{
println!("Error: both link_shared_librosie and build_static_librosie are specified");
return Err(-1);
}
#[cfg(feature = "link_shared_librosie")]
{
let librosie = pkg_config::Config::new()
.cargo_metadata(true)
.print_system_libs(true)
.atleast_version("1.3.0")
.probe("rosie");
if librosie.is_ok() {
return Ok(());
}
if librosie_installed() {
println!("cargo:rustc-link-lib=rosie");
return Ok(());
}
println!("Error: link_shared_librosie specified, but librosie 1.3.0 or higher couldn't be found");
return Err(-1);
}
#[cfg(feature = "build_static_librosie")]
{
if librosie_src_build() {
println!("cargo:rustc-link-lib=rosie");
return Ok(());
}
println!("Error: librosie build failure");
return Err(-1);
}
#[cfg(not(any(feature = "link_shared_librosie", feature = "build_static_librosie")))]
{
println!("Error: either the link_shared_librosie or build_static_librosie feature must be specified");
return Err(-1);
}
}
fn librosie_installed() -> bool {
let smoke_file : PathBuf = ["src", "smoke.c"].iter().collect();
let mut cfg = cc::Build::new();
cfg.cargo_metadata(false);
cfg.file(smoke_file);
if cfg.try_compile("smoke").is_ok() {
return true;
}
false
}
fn librosie_src_build() -> bool {
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
let rosie_lib_dir = out_dir.clone(); let rosie_include_dir = out_dir.join("include");
let rosie_home_dir = out_dir.join("rosie_home");
let lua_cjson_dir : PathBuf = ["src", "lua-cjson"].iter().collect();
let rpeg_src_dir : PathBuf = ["src", "rpeg"].iter().collect();
let rpeg_compiler_dir = rpeg_src_dir.join("compiler");
let rpeg_runtime_dir = rpeg_src_dir.join("runtime");
let librosie_src_dir : PathBuf = ["src", "librosie"].iter().collect();
let rosie_include_src_dir = manifest_dir.join(&librosie_src_dir);
let rosie_home_src_dir = manifest_dir.join("src").join("rosie_home");
let lua_include_dir = PathBuf::from(std::env::var_os("DEP_LUA_INCLUDE").unwrap());
let lua_lib_dir = PathBuf::from(std::env::var_os("DEP_LUA_LIB").unwrap());
println!("cargo:rustc-link-search={}", lua_lib_dir.display());
println!("cargo:rustc-link-lib=static=lua5.3");
let compile_src_files : Vec<PathBuf> = vec![
lua_cjson_dir.join("fpconv.c"),
lua_cjson_dir.join("strbuf.c"),
lua_cjson_dir.join("lua_cjson.c"),
rpeg_compiler_dir.join("rbuf.c"),
rpeg_compiler_dir.join("lpcap.c"),
rpeg_compiler_dir.join("lptree.c"),
rpeg_compiler_dir.join("lpcode.c"),
rpeg_compiler_dir.join("lpprint.c"),
rpeg_runtime_dir.join("buf.c"),
rpeg_runtime_dir.join("capture.c"),
rpeg_runtime_dir.join("file.c"),
rpeg_runtime_dir.join("json.c"),
rpeg_runtime_dir.join("ktable.c"),
rpeg_runtime_dir.join("rplx.c"),
rpeg_runtime_dir.join("vm.c"),
librosie_src_dir.join("librosie.c"),
];
let mut cfg = cc::Build::new();
cfg.static_flag(true);
cfg.include(lua_include_dir);
cfg.include(rpeg_src_dir.join("include"));
cfg.define("LPEG_DEBUG", None); cfg.define("NDEBUG", None); cfg.define("LUA_COMPAT_5_2", None); cfg.define("_GNU_SOURCE", None); cfg.files(compile_src_files.iter());
cfg.compile("rosie");
println!("cargo:rerun-if-changed=src");
let rosie_home_files : Vec<PathBuf> = vec![
PathBuf::from("CHANGELOG"),
PathBuf::from("CONTRIBUTORS"),
PathBuf::from("LICENSE"),
PathBuf::from("README"),
PathBuf::from("VERSION"),
PathBuf::from("lib").join("argparse.luac"),
PathBuf::from("lib").join("ast.luac"),
PathBuf::from("lib").join("boot.luac"),
PathBuf::from("lib").join("builtins.luac"),
PathBuf::from("lib").join("cli-common.luac"),
PathBuf::from("lib").join("cli-match.luac"),
PathBuf::from("lib").join("cli-parser.luac"),
PathBuf::from("lib").join("cli.luac"),
PathBuf::from("lib").join("color.luac"),
PathBuf::from("lib").join("common.luac"),
PathBuf::from("lib").join("compile.luac"),
PathBuf::from("lib").join("engine_module.luac"),
PathBuf::from("lib").join("environment.luac"),
PathBuf::from("lib").join("expand.luac"),
PathBuf::from("lib").join("expr.luac"),
PathBuf::from("lib").join("infix.luac"),
PathBuf::from("lib").join("init.luac"),
PathBuf::from("lib").join("list.luac"),
PathBuf::from("lib").join("loadpkg.luac"),
PathBuf::from("lib").join("parse.luac"),
PathBuf::from("lib").join("parse_core.luac"),
PathBuf::from("lib").join("rcfile.luac"),
PathBuf::from("lib").join("recordtype.luac"),
PathBuf::from("lib").join("repl.luac"),
PathBuf::from("lib").join("strict.luac"),
PathBuf::from("lib").join("submodule.luac"),
PathBuf::from("lib").join("thread.luac"),
PathBuf::from("lib").join("trace.luac"),
PathBuf::from("lib").join("ui.luac"),
PathBuf::from("lib").join("unittest.luac"),
PathBuf::from("lib").join("ustring.luac"),
PathBuf::from("lib").join("util.luac"),
PathBuf::from("lib").join("violation.luac"),
PathBuf::from("lib").join("writer.luac"),
PathBuf::from("rpl").join("all.rpl"),
PathBuf::from("rpl").join("char.rpl"),
PathBuf::from("rpl").join("csv.rpl"),
PathBuf::from("rpl").join("date.rpl"),
PathBuf::from("rpl").join("id.rpl"),
PathBuf::from("rpl").join("json.rpl"),
PathBuf::from("rpl").join("net.rpl"),
PathBuf::from("rpl").join("num.rpl"),
PathBuf::from("rpl").join("os.rpl"),
PathBuf::from("rpl").join("re.rpl"),
PathBuf::from("rpl").join("time.rpl"),
PathBuf::from("rpl").join("ts.rpl"),
PathBuf::from("rpl").join("ver.rpl"),
PathBuf::from("rpl").join("word.rpl"),
PathBuf::from("rpl").join("Unicode").join("Ascii.rpl"),
PathBuf::from("rpl").join("Unicode").join("Block.rpl"),
PathBuf::from("rpl").join("Unicode").join("Category.rpl"),
PathBuf::from("rpl").join("Unicode").join("GraphemeBreak.rpl"),
PathBuf::from("rpl").join("Unicode").join("LineBreak.rpl"),
PathBuf::from("rpl").join("Unicode").join("NumericType.rpl"),
PathBuf::from("rpl").join("Unicode").join("Property.rpl"),
PathBuf::from("rpl").join("Unicode").join("Script.rpl"),
PathBuf::from("rpl").join("Unicode").join("SentenceBreak.rpl"),
PathBuf::from("rpl").join("Unicode").join("WordBreak.rpl"),
PathBuf::from("rpl").join("builtin").join("prelude.rpl"),
PathBuf::from("rpl").join("rosie").join("rcfile.rpl"),
PathBuf::from("rpl").join("rosie").join("rpl_1_1.rpl"),
PathBuf::from("rpl").join("rosie").join("rpl_1_2.rpl"),
PathBuf::from("rpl").join("rosie").join("rpl_1_3.rpl"),
];
create_empty_dir(&rosie_home_dir).unwrap();
for file in &rosie_home_files {
let dest_path = rosie_home_dir.join(file);
create_parent_dir(&dest_path).unwrap();
fs::copy(rosie_home_src_dir.join(file), dest_path).unwrap();
}
println!("cargo:rustc-env=ROSIE_HOME={}", rosie_home_dir.display());
create_empty_dir(&rosie_include_dir).unwrap();
for include_file in &["librosie.h"] {
fs::copy(rosie_include_src_dir.join(include_file), rosie_include_dir.join(include_file)).unwrap();
}
println!("cargo:include={}", rosie_include_dir.display());
println!("cargo:lib={}", rosie_lib_dir.display());
true
}
fn create_empty_dir<P: AsRef<Path>>(path: P) -> Result<(), std::io::Error> {
if path.as_ref().exists() {
fs::remove_dir_all(&path)?;
}
fs::create_dir_all(&path)
}
fn create_parent_dir<P: AsRef<Path>>(path: P) -> Result<(), std::io::Error> {
let parent = path.as_ref().parent().ok_or(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("Can't get parent of path: {}", path.as_ref().display())))?;
fs::create_dir_all(&parent)
}