Skip to content

Commit

Permalink
feat(deployer): add support for building wasm projects
Browse files Browse the repository at this point in the history
  • Loading branch information
akrantz01 committed Oct 27, 2022
1 parent da46e60 commit db28a73
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 31 deletions.
7 changes: 5 additions & 2 deletions cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crossterm::style::Stylize;
use factory::LocalFactory;
use futures::StreamExt;
use shuttle_common::models::secret;
use shuttle_service::loader::{build_crate, Loader};
use shuttle_service::loader::{build_crate, Loader, Runtime};
use shuttle_service::Logger;
use tokio::sync::mpsc;
use tracing::trace;
Expand Down Expand Up @@ -277,7 +277,10 @@ impl Shuttle {
"Building".bold().green(),
working_directory.display()
);
let so_path = build_crate(id, working_directory, false, tx).await?;
let so_path = match build_crate(id, working_directory, false, false, tx).await? {
Runtime::Legacy(path) => path,
Runtime::Next(_) => todo!(),
};

trace!("loading secrets");
let secrets_path = working_directory.join("Secrets.toml");
Expand Down
12 changes: 8 additions & 4 deletions deployer/src/deployment/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cargo_metadata::Message;
use chrono::Utc;
use crossbeam_channel::Sender;
use serde_json::json;
use shuttle_service::loader::{build_crate, get_config};
use shuttle_service::loader::{build_crate, get_config, Runtime};
use tracing::{debug, error, info, instrument, trace};
use uuid::Uuid;

Expand Down Expand Up @@ -158,7 +158,7 @@ impl Queued {
});

let project_path = project_path.canonicalize()?;
let so_path = build_deployment(self.id, &project_path, tx.clone()).await?;
let so_path = build_deployment(self.id, &project_path, false, tx.clone()).await?;

if self.will_run_tests {
info!(
Expand Down Expand Up @@ -265,13 +265,17 @@ fn extract_tar_gz_data(data: impl Read, dest: impl AsRef<Path>) -> Result<()> {
async fn build_deployment(
deployment_id: Uuid,
project_path: &Path,
wasm: bool,
tx: crossbeam_channel::Sender<Message>,
) -> Result<PathBuf> {
let so_path = build_crate(deployment_id, project_path, true, tx)
let runtime_path = build_crate(deployment_id, project_path, true, wasm, tx)
.await
.map_err(|e| Error::Build(e.into()))?;

Ok(so_path)
match runtime_path {
Runtime::Legacy(so_path) => Ok(so_path),
Runtime::Next(_) => todo!(),
}
}

#[instrument(skip(project_path, tx))]
Expand Down
32 changes: 27 additions & 5 deletions service/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::panic::AssertUnwindSafe;
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context};
use cargo::core::compiler::{CompileMode, MessageFormat};
use cargo::core::compiler::{CompileKind, CompileMode, CompileTarget, MessageFormat};
use cargo::core::{Manifest, PackageId, Shell, Summary, Verbosity, Workspace};
use cargo::ops::{compile, CompileOptions};
use cargo::util::interning::InternedString;
Expand Down Expand Up @@ -100,13 +100,20 @@ impl Loader {
}
}

/// How to run/build the project
pub enum Runtime {
Next(PathBuf),
Legacy(PathBuf),
}

/// Given a project directory path, builds the crate
pub async fn build_crate(
deployment_id: Uuid,
project_path: &Path,
release_mode: bool,
wasm: bool,
tx: Sender<Message>,
) -> anyhow::Result<PathBuf> {
) -> anyhow::Result<Runtime> {
let (read, write) = pipe::pipe();
let project_path = project_path.to_owned();

Expand All @@ -125,10 +132,15 @@ pub async fn build_crate(
check_version(summary)?;
check_no_panic(&ws)?;

let opts = get_compile_options(&config, release_mode)?;
let opts = get_compile_options(&config, release_mode, wasm)?;
let compilation = compile(&ws, &opts);

Ok(compilation?.cdylibs[0].path.clone())
let path = compilation?.cdylibs[0].path.clone();
Ok(if wasm {
Runtime::Next(path)
} else {
Runtime::Legacy(path)
})
});

// This needs to be on a separate thread, else deployer will block (reason currently unknown :D)
Expand Down Expand Up @@ -169,7 +181,11 @@ pub fn get_config(writer: PipeWriter) -> anyhow::Result<Config> {
}

/// Get options to compile in build mode
fn get_compile_options(config: &Config, release_mode: bool) -> anyhow::Result<CompileOptions> {
fn get_compile_options(
config: &Config,
release_mode: bool,
wasm: bool,
) -> anyhow::Result<CompileOptions> {
let mut opts = CompileOptions::new(config, CompileMode::Build)?;
opts.build_config.message_format = MessageFormat::Json {
render_diagnostics: false,
Expand All @@ -183,6 +199,12 @@ fn get_compile_options(config: &Config, release_mode: bool) -> anyhow::Result<Co
InternedString::new("dev")
};

opts.build_config.requested_kinds = vec![if wasm {
CompileKind::Target(CompileTarget::new("wasm32-unknown-unknown")?)
} else {
CompileKind::Host
}];

Ok(opts)
}

Expand Down
74 changes: 54 additions & 20 deletions service/tests/integration/build_crate.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
use std::path::{Path, PathBuf};

use shuttle_service::loader::build_crate;
use shuttle_service::loader::{build_crate, Runtime};

#[tokio::test(flavor = "multi_thread")]
async fn not_shuttle() {
let (tx, _) = crossbeam_channel::unbounded();
let project_path = format!("{}/tests/resources/not-shuttle", env!("CARGO_MANIFEST_DIR"));
let so_path = build_crate(Default::default(), Path::new(&project_path), false, tx)
.await
.unwrap();
let so_path = match build_crate(
Default::default(),
Path::new(&project_path),
false,
false,
tx,
)
.await
.unwrap()
{
Runtime::Legacy(path) => path,
_ => unreachable!(),
};

assert!(
so_path
Expand All @@ -27,20 +37,32 @@ async fn not_shuttle() {
async fn not_lib() {
let (tx, _) = crossbeam_channel::unbounded();
let project_path = format!("{}/tests/resources/not-lib", env!("CARGO_MANIFEST_DIR"));
build_crate(Default::default(), Path::new(&project_path), false, tx)
.await
.unwrap();
build_crate(
Default::default(),
Path::new(&project_path),
false,
false,
tx,
)
.await
.unwrap();
}

#[tokio::test(flavor = "multi_thread")]
async fn not_cdylib() {
let (tx, _) = crossbeam_channel::unbounded();
let project_path = format!("{}/tests/resources/not-cdylib", env!("CARGO_MANIFEST_DIR"));
assert!(
build_crate(Default::default(), Path::new(&project_path), false, tx)
.await
.is_ok()
);
assert!(matches!(
build_crate(
Default::default(),
Path::new(&project_path),
false,
false,
tx
)
.await,
Ok(Runtime::Legacy(_))
));
assert!(PathBuf::from(project_path)
.join("target/debug/libnot_cdylib.so")
.exists());
Expand All @@ -50,11 +72,17 @@ async fn not_cdylib() {
async fn is_cdylib() {
let (tx, _) = crossbeam_channel::unbounded();
let project_path = format!("{}/tests/resources/is-cdylib", env!("CARGO_MANIFEST_DIR"));
assert!(
build_crate(Default::default(), Path::new(&project_path), false, tx)
.await
.is_ok()
);
assert!(matches!(
build_crate(
Default::default(),
Path::new(&project_path),
false,
false,
tx
)
.await,
Ok(Runtime::Legacy(_))
));
assert!(PathBuf::from(project_path)
.join("target/debug/libis_cdylib.so")
.exists());
Expand All @@ -68,7 +96,13 @@ async fn not_found() {
"{}/tests/resources/non-existing",
env!("CARGO_MANIFEST_DIR")
);
build_crate(Default::default(), Path::new(&project_path), false, tx)
.await
.unwrap();
build_crate(
Default::default(),
Path::new(&project_path),
false,
false,
tx,
)
.await
.unwrap();
}

0 comments on commit db28a73

Please sign in to comment.