From 9fcbbbe0e50c4da32b801a7b51e964ee9f361a93 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 14 Sep 2020 14:16:26 +0200 Subject: [PATCH 1/2] feat(native-engine) Panic if `gcc`/`clang-10` is missing. --- lib/engine-native/Cargo.toml | 1 + lib/engine-native/src/engine.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/engine-native/Cargo.toml b/lib/engine-native/Cargo.toml index 10b01d2487b..908753abffd 100644 --- a/lib/engine-native/Cargo.toml +++ b/lib/engine-native/Cargo.toml @@ -23,6 +23,7 @@ bincode = "1.3" leb128 = "0.2" libloading = "0.6" tempfile = "3.1" +which = "4.0" [features] # Enable the `compiler` feature if you want the engine to compile diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index 5eb30d7024b..e4189c66884 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -13,6 +13,8 @@ use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables}; use wasmer_types::Features; use wasmer_types::FunctionType; use wasmer_vm::{SignatureRegistry, VMSharedSignatureIndex, VMTrampoline}; +#[cfg(feature = "compiler")] +use which::which; /// A WebAssembly `Native` Engine. #[derive(Clone)] @@ -27,6 +29,10 @@ impl NativeEngine { /// Create a new `NativeEngine` with the given config #[cfg(feature = "compiler")] pub fn new(compiler: Box, target: Target, features: Features) -> Self { + if let Err(_) = which("gcc").or_else(|_| which("clang-10")) { + panic!("gcc/clang is not found, it is required for using the `NativeEngine`"); + } + Self { inner: Arc::new(Mutex::new(NativeEngineInner { compiler: Some(compiler), From cd8798378c627e1e7e58bb34b33e08bb9ccc02f8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 14 Sep 2020 15:29:31 +0200 Subject: [PATCH 2/2] feat(engine-native) Store cross-compilation and proper `Linker` type inside `NativeEngineInner`. --- lib/engine-native/src/artifact.rs | 12 ++----- lib/engine-native/src/engine.rs | 56 ++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 237e6b2d72d..cefde4d8d6a 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -256,8 +256,7 @@ impl NativeArtifact { .map_err(to_compile_error)? }; - let host_target = Triple::host(); - let is_cross_compiling = target_triple != &host_target; + let is_cross_compiling = engine_inner.is_cross_compiling(); let cross_compiling_args: Vec = if is_cross_compiling { vec![ format!("--target={}", target_triple), @@ -276,15 +275,10 @@ impl NativeArtifact { trace!( "Compiling for target {} from host {}", target_triple.to_string(), - host_target.to_string() + Triple::host().to_string(), ); - let linker = if is_cross_compiling { - "clang-10" - } else { - "gcc" - }; - + let linker: &'static str = engine_inner.linker().into(); let output = Command::new(linker) .arg(&filepath) .arg("-o") diff --git a/lib/engine-native/src/engine.rs b/lib/engine-native/src/engine.rs index e4189c66884..5e19af64e18 100644 --- a/lib/engine-native/src/engine.rs +++ b/lib/engine-native/src/engine.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::sync::Mutex; #[cfg(feature = "compiler")] use wasmer_compiler::Compiler; -use wasmer_compiler::{CompileError, Target}; +use wasmer_compiler::{CompileError, Target, Triple}; use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables}; #[cfg(feature = "compiler")] use wasmer_types::Features; @@ -29,9 +29,22 @@ impl NativeEngine { /// Create a new `NativeEngine` with the given config #[cfg(feature = "compiler")] pub fn new(compiler: Box, target: Target, features: Features) -> Self { - if let Err(_) = which("gcc").or_else(|_| which("clang-10")) { - panic!("gcc/clang is not found, it is required for using the `NativeEngine`"); - } + let host_target = Triple::host(); + let is_cross_compiling = target.triple() != &host_target; + + let linker = if is_cross_compiling { + which(Into::<&'static str>::into(Linker::Clang10)) + .map(|_| Linker::Clang10) + .or_else(|_| { + which(Into::<&'static str>::into(Linker::Clang)) + .map(|_| Linker::Clang) + }) + .expect("Nor `clang-10` or `clang` has been found, at least one of them is required for the `NativeEngine`") + } else { + which(Into::<&'static str>::into(Linker::Gcc)) + .map(|_| Linker::Gcc) + .expect("`gcc` has not been found, it is required for the `NativeEngine`") + }; Self { inner: Arc::new(Mutex::new(NativeEngineInner { @@ -40,6 +53,8 @@ impl NativeEngine { signatures: SignatureRegistry::new(), prefixer: None, features, + is_cross_compiling, + linker, })), target: Arc::new(target), engine_id: EngineId::default(), @@ -69,6 +84,8 @@ impl NativeEngine { trampolines: HashMap::new(), signatures: SignatureRegistry::new(), prefixer: None, + is_cross_compiling: false, + linker: Linker::None, })), target: Arc::new(Target::default()), engine_id: EngineId::default(), @@ -178,6 +195,25 @@ impl Engine for NativeEngine { } } +#[derive(Clone, Copy)] +pub(crate) enum Linker { + None, + Clang10, + Clang, + Gcc, +} + +impl Into<&'static str> for Linker { + fn into(self) -> &'static str { + match self { + Self::None => "", + Self::Clang10 => "clang-10", + Self::Clang => "clang", + Self::Gcc => "gcc", + } + } +} + /// The inner contents of `NativeEngine` pub struct NativeEngineInner { /// The compiler @@ -195,6 +231,10 @@ pub struct NativeEngineInner { /// the functions in the shared object generated by the `NativeEngine`, /// so we can assure no collisions. prefixer: Option String + Send>>, + /// Whether the native engine will cross-compile. + is_cross_compiling: bool, + /// The linker to use. + linker: Linker, } impl NativeEngineInner { @@ -255,4 +295,12 @@ impl NativeEngineInner { // where they belong become unallocated. self.trampolines.insert(index, trampoline); } + + pub(crate) fn is_cross_compiling(&self) -> bool { + self.is_cross_compiling + } + + pub(crate) fn linker(&self) -> Linker { + self.linker + } }