2020-01-25 14:25:55 -05:00
|
|
|
#![allow(unreachable_code)]
|
|
|
|
|
|
|
|
use std::env;
|
2021-01-14 20:15:36 -05:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::{Error, ErrorKind, Result, Write};
|
2020-01-25 14:25:55 -05:00
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use std::process::Command;
|
|
|
|
|
2020-05-31 07:16:47 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
all(
|
|
|
|
feature = "vendored",
|
|
|
|
any(
|
|
|
|
feature = "lua54",
|
|
|
|
feature = "lua53",
|
|
|
|
feature = "lua52",
|
|
|
|
feature = "lua51",
|
|
|
|
feature = "luajit"
|
|
|
|
)
|
|
|
|
),
|
|
|
|
path = "find_vendored.rs"
|
|
|
|
)]
|
|
|
|
#[cfg_attr(
|
|
|
|
all(
|
|
|
|
not(feature = "vendored"),
|
|
|
|
any(
|
|
|
|
feature = "lua54",
|
|
|
|
feature = "lua53",
|
|
|
|
feature = "lua52",
|
|
|
|
feature = "lua51",
|
|
|
|
feature = "luajit"
|
|
|
|
)
|
|
|
|
),
|
|
|
|
path = "find_normal.rs"
|
|
|
|
)]
|
|
|
|
#[cfg_attr(
|
|
|
|
not(any(
|
|
|
|
feature = "lua54",
|
|
|
|
feature = "lua53",
|
|
|
|
feature = "lua52",
|
|
|
|
feature = "lua51",
|
|
|
|
feature = "luajit"
|
|
|
|
)),
|
|
|
|
path = "find_dummy.rs"
|
|
|
|
)]
|
2020-01-25 14:25:55 -05:00
|
|
|
mod find;
|
|
|
|
|
|
|
|
trait CommandExt {
|
|
|
|
fn execute(&mut self) -> Result<()>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CommandExt for Command {
|
|
|
|
/// Execute the command and return an error if it exited with a failure status.
|
|
|
|
fn execute(&mut self) -> Result<()> {
|
|
|
|
self.status()
|
|
|
|
.and_then(|status| {
|
|
|
|
if status.success() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(Error::new(ErrorKind::Other, "non-zero exit code"))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map_err(|_| {
|
|
|
|
Error::new(
|
|
|
|
ErrorKind::Other,
|
|
|
|
format!("The command {:?} did not run successfully.", self),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_glue<P: AsRef<Path> + std::fmt::Debug>(include_path: &P) {
|
|
|
|
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
|
|
|
|
|
|
|
let mut config = cc::Build::new();
|
|
|
|
config.include(include_path);
|
|
|
|
|
|
|
|
// Compile and run glue.c
|
|
|
|
let glue = build_dir.join("glue");
|
|
|
|
|
|
|
|
config
|
|
|
|
.get_compiler()
|
|
|
|
.to_command()
|
|
|
|
.arg("src/ffi/glue/glue.c")
|
|
|
|
.arg("-o")
|
|
|
|
.arg(&glue)
|
|
|
|
.execute()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
Command::new(glue)
|
|
|
|
.arg(build_dir.join("glue.rs"))
|
|
|
|
.execute()
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2021-01-13 12:55:53 -05:00
|
|
|
// When cross-compiling, we cannot use `build_glue` as we cannot run the generated
|
|
|
|
// executable. Instead, let's take a stab at synthesizing the likely values.
|
|
|
|
// If you're cross-compiling and using a non-vendored library then there is a chance
|
|
|
|
// that the values selected here may be incorrect, but we have no way to determine
|
|
|
|
// that here.
|
2021-01-14 20:15:36 -05:00
|
|
|
fn generate_glue() -> Result<()> {
|
2021-01-13 12:55:53 -05:00
|
|
|
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
2021-01-14 20:15:36 -05:00
|
|
|
let mut glue = File::create(build_dir.join("glue.rs"))?;
|
|
|
|
writeln!(
|
2021-01-13 12:55:53 -05:00
|
|
|
glue,
|
2021-01-14 20:15:36 -05:00
|
|
|
"/* This file was generated by build/main.rs; do not modify by hand */"
|
2021-01-13 12:55:53 -05:00
|
|
|
)?;
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "use std::os::raw::*;")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "/* luaconf.h */")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
let pointer_bit_width: usize = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
|
|
|
|
.unwrap()
|
|
|
|
.parse()
|
|
|
|
.unwrap();
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(
|
2021-01-13 12:55:53 -05:00
|
|
|
glue,
|
2021-01-14 20:15:36 -05:00
|
|
|
"pub const LUA_EXTRASPACE: c_int = {} / 8;",
|
2021-01-13 12:55:53 -05:00
|
|
|
pointer_bit_width
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// This is generally hardcoded to this size
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "pub const LUA_IDSIZE: c_int = 60;")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
|
|
|
|
// Unless the target is restricted, the defaults are 64 bit
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "pub type LUA_NUMBER = c_double;")?;
|
|
|
|
writeln!(glue, "pub type LUA_INTEGER = i64;")?;
|
|
|
|
writeln!(glue, "pub type LUA_UNSIGNED = u64;")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "/* lua.h */")?;
|
|
|
|
let version = if cfg!(any(feature = "luajit", feature = "lua51")) {
|
2021-01-13 12:55:53 -05:00
|
|
|
(5, 1, 0)
|
|
|
|
} else if cfg!(feature = "lua52") {
|
|
|
|
(5, 2, 0)
|
|
|
|
} else if cfg!(feature = "lua53") {
|
|
|
|
(5, 3, 0)
|
|
|
|
} else if cfg!(feature = "lua54") {
|
|
|
|
(5, 4, 0)
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
};
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(
|
2021-01-13 12:55:53 -05:00
|
|
|
glue,
|
2021-01-14 20:15:36 -05:00
|
|
|
"pub const LUA_VERSION_NUM: c_int = {};",
|
2021-01-13 12:55:53 -05:00
|
|
|
(version.0 * 100) + version.1
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let max_stack = if pointer_bit_width >= 32 {
|
|
|
|
1_000_000
|
|
|
|
} else {
|
|
|
|
15_000
|
|
|
|
};
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(
|
2021-01-13 12:55:53 -05:00
|
|
|
glue,
|
2021-01-14 20:15:36 -05:00
|
|
|
"pub const LUA_REGISTRYINDEX: c_int = -{} - 1000;",
|
2021-01-13 12:55:53 -05:00
|
|
|
max_stack
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// These two are only defined in lua 5.1
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "pub const LUA_ENVIRONINDEX: c_int = -10001;")?;
|
|
|
|
writeln!(glue, "pub const LUA_GLOBALSINDEX: c_int = -10002;")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "/* lauxlib.h */")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
// This is only defined in lua 5.3 and up, but we can always generate its value here,
|
|
|
|
// even if we don't use it.
|
|
|
|
// This matches the default definition in lauxlib.h
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "pub const LUAL_NUMSIZES: c_int = std::mem::size_of::<LUA_INTEGER>() as c_int * 16 + std::mem::size_of::<LUA_NUMBER>() as c_int;")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
|
2021-01-14 20:15:36 -05:00
|
|
|
writeln!(glue, "/* lualib.h */")?;
|
2021-01-13 12:55:53 -05:00
|
|
|
write!(
|
|
|
|
glue,
|
|
|
|
r#"
|
2021-01-13 23:01:12 -05:00
|
|
|
#[cfg(feature = "luajit")]
|
|
|
|
pub const LUA_BITLIBNAME: &str = "bit";
|
|
|
|
#[cfg(not(feature = "luajit"))]
|
2021-01-13 12:55:53 -05:00
|
|
|
pub const LUA_BITLIBNAME: &str = "bit32";
|
2021-01-13 23:01:12 -05:00
|
|
|
|
2021-01-13 12:55:53 -05:00
|
|
|
pub const LUA_COLIBNAME: &str = "coroutine";
|
|
|
|
pub const LUA_DBLIBNAME: &str = "debug";
|
|
|
|
pub const LUA_IOLIBNAME: &str = "io";
|
|
|
|
pub const LUA_LOADLIBNAME: &str = "package";
|
|
|
|
pub const LUA_MATHLIBNAME: &str = "math";
|
|
|
|
pub const LUA_OSLIBNAME: &str = "os";
|
|
|
|
pub const LUA_STRLIBNAME: &str = "string";
|
|
|
|
pub const LUA_TABLIBNAME: &str = "table";
|
|
|
|
pub const LUA_UTF8LIBNAME: &str = "utf8";
|
|
|
|
|
2021-01-13 23:01:12 -05:00
|
|
|
pub const LUA_JITLIBNAME: &str = "jit";
|
|
|
|
pub const LUA_FFILIBNAME: &str = "ffi";
|
2021-01-13 12:55:53 -05:00
|
|
|
"#
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-01-25 14:25:55 -05:00
|
|
|
fn main() {
|
|
|
|
#[cfg(not(any(
|
2020-05-08 07:42:40 -04:00
|
|
|
feature = "lua54",
|
2020-01-25 14:25:55 -05:00
|
|
|
feature = "lua53",
|
|
|
|
feature = "lua52",
|
|
|
|
feature = "lua51",
|
|
|
|
feature = "luajit"
|
|
|
|
)))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!("You must enable one of the features: lua54, lua53, lua52, lua51, luajit");
|
2020-05-08 07:42:40 -04:00
|
|
|
|
|
|
|
#[cfg(all(
|
|
|
|
feature = "lua54",
|
|
|
|
any(
|
|
|
|
feature = "lua53",
|
|
|
|
feature = "lua52",
|
|
|
|
feature = "lua51",
|
|
|
|
feature = "luajit"
|
|
|
|
)
|
|
|
|
))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
|
2020-01-25 14:25:55 -05:00
|
|
|
|
|
|
|
#[cfg(all(
|
|
|
|
feature = "lua53",
|
|
|
|
any(feature = "lua52", feature = "lua51", feature = "luajit")
|
|
|
|
))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
|
2020-01-25 14:25:55 -05:00
|
|
|
|
|
|
|
#[cfg(all(feature = "lua52", any(feature = "lua51", feature = "luajit")))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
|
2020-01-25 14:25:55 -05:00
|
|
|
|
|
|
|
#[cfg(all(feature = "lua51", feature = "luajit"))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!("You can enable only one of the features: lua54, lua53, lua52, lua51, luajit");
|
2020-01-25 14:25:55 -05:00
|
|
|
|
2020-05-31 07:16:47 -04:00
|
|
|
// We don't support "vendored module" mode on windows
|
|
|
|
#[cfg(all(feature = "vendored", feature = "module", target_os = "windows"))]
|
2020-06-05 18:27:56 -04:00
|
|
|
compile_error!(
|
2020-05-31 07:16:47 -04:00
|
|
|
"Vendored (static) builds are not supported for modules on Windows.\n"
|
|
|
|
+ "Please, use `pkg-config` or custom mode to link to a Lua dll."
|
|
|
|
);
|
|
|
|
|
2020-01-25 14:25:55 -05:00
|
|
|
let include_dir = find::probe_lua();
|
2021-01-13 12:55:53 -05:00
|
|
|
if env::var("TARGET").unwrap() != env::var("HOST").unwrap() {
|
|
|
|
generate_glue().unwrap();
|
|
|
|
} else {
|
|
|
|
build_glue(&include_dir);
|
2021-04-14 17:33:14 -04:00
|
|
|
println!("cargo:rerun-if-changed=src/ffi/glue/glue.c");
|
2021-01-13 12:55:53 -05:00
|
|
|
}
|
2021-04-14 17:33:14 -04:00
|
|
|
|
2021-04-09 07:05:03 -04:00
|
|
|
let mut shim_cc = cc::Build::new();
|
|
|
|
shim_cc
|
|
|
|
.include(include_dir)
|
2021-06-12 13:00:55 -04:00
|
|
|
.file("src/ffi/shim/symbols.c")
|
|
|
|
.compile("shim");
|
2021-04-09 07:05:03 -04:00
|
|
|
|
|
|
|
println!("cargo:rerun-if-changed=src/ffi/shim");
|
2021-04-14 17:33:14 -04:00
|
|
|
println!("cargo:rerun-if-changed=build");
|
2020-01-25 14:25:55 -05:00
|
|
|
}
|