1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
use crate::{
features::is_env_variable_defined,
version::{Version, MIN_SUPPORTED_STABLE_VERSION},
};
use std::{convert::TryFrom, error::Error, path::Path};
pub fn setup(current_ruby_version: Version) -> Result<(), Box<dyn Error>> {
let strategy = Strategy::try_from(current_ruby_version)?;
strategy.apply()?;
Ok(())
}
#[derive(Debug)]
enum Strategy {
RustOnly(Version),
CompiledOnly,
RustThenCompiled(Version),
Testing(Version),
}
impl TryFrom<Version> for Strategy {
type Error = Box<dyn Error>;
fn try_from(current_ruby_version: Version) -> Result<Self, Self::Error> {
let mut strategy = None;
if current_ruby_version.is_stable() {
strategy = Some(Strategy::RustOnly(current_ruby_version));
} else {
maybe_warn_old_ruby_version(current_ruby_version);
}
if is_fallback_enabled() {
strategy = Some(Strategy::RustThenCompiled(current_ruby_version));
}
if is_testing() {
strategy = Some(Strategy::Testing(current_ruby_version));
}
if is_force_enabled() {
strategy = Some(Strategy::CompiledOnly);
}
if let Some(strategy) = strategy {
return Ok(strategy);
}
Err("Stable API is needed but could not find a candidate. Try enabling the `stable-api-compiled-fallback` feature in rb-sys.".into())
}
}
impl Strategy {
fn apply(self) -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-check-cfg=cfg(stable_api_include_rust_impl)");
println!("cargo:rustc-check-cfg=cfg(stable_api_enable_compiled_mod)");
println!("cargo:rustc-check-cfg=cfg(stable_api_export_compiled_as_api)");
println!("cargo:rustc-check-cfg=cfg(stable_api_has_rust_impl)");
match self {
Strategy::RustOnly(current_ruby_version) => {
if current_ruby_version.is_stable() {
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
} else {
return Err(format!("A stable Ruby API is needed but could not find a candidate. If you are using a stable version of Ruby, try upgrading rb-sys. Otherwise if you are testing against ruby-head or Ruby < {}, enable the `stable-api-compiled-fallback` feature in rb-sys.", MIN_SUPPORTED_STABLE_VERSION).into());
}
}
Strategy::CompiledOnly => {
compile()?;
println!("cargo:rustc-cfg=stable_api_enable_compiled_mod");
println!("cargo:rustc-cfg=stable_api_export_compiled_as_api");
}
Strategy::RustThenCompiled(current_ruby_version) => {
if current_ruby_version.is_stable() {
println!("cargo:rustc-cfg=stable_api_has_rust_impl");
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
} else {
compile()?;
println!("cargo:rustc-cfg=stable_api_enable_compiled_mod");
println!("cargo:rustc-cfg=stable_api_export_compiled_as_api");
}
}
Strategy::Testing(current_ruby_version) => {
compile()?;
println!("cargo:rustc-cfg=stable_api_enable_compiled_mod");
if current_ruby_version.is_stable() {
println!("cargo:rustc-cfg=stable_api_include_rust_impl");
} else {
println!("cargo:rustc-cfg=stable_api_export_compiled_as_api");
}
}
};
Ok(())
}
}
fn is_fallback_enabled() -> bool {
println!("cargo:rerun-if-env-changed=RB_SYS_STABLE_API_COMPILED_FALLBACK");
is_env_variable_defined("CARGO_FEATURE_STABLE_API_COMPILED_FALLBACK")
|| cfg!(rb_sys_use_stable_api_compiled_fallback)
|| is_env_variable_defined("RB_SYS_STABLE_API_COMPILED_FALLBACK")
}
fn is_force_enabled() -> bool {
println!("cargo:rerun-if-env-changed=RB_SYS_STABLE_API_COMPILED_FORCE");
is_env_variable_defined("CARGO_FEATURE_STABLE_API_COMPILED_FORCE")
|| cfg!(rb_sys_force_stable_api_compiled)
|| is_env_variable_defined("RB_SYS_STABLE_API_COMPILED_FORCE")
}
fn is_testing() -> bool {
is_env_variable_defined("CARGO_FEATURE_STABLE_API_COMPILED_TESTING")
}
fn maybe_warn_old_ruby_version(current_ruby_version: Version) {
if current_ruby_version < MIN_SUPPORTED_STABLE_VERSION {
println!(
"cargo:warning=Support for Ruby {} will be removed in a future release.",
current_ruby_version
);
}
}
fn compile() -> Result<(), Box<dyn Error>> {
eprintln!("INFO: Compiling the stable API compiled module");
let mut build = rb_sys_build::cc::Build::new();
let crate_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let path = crate_dir.join("src").join("stable_api").join("compiled.c");
eprintln!("cargo:rerun-if-changed={}", path.display());
build.file(path);
build.try_compile("compiled")
}
|