Skip to content

Commit

Permalink
Compile locally defined packages
Browse files Browse the repository at this point in the history
  • Loading branch information
mara-schulke committed Aug 15, 2023
1 parent 68ce8ea commit 09f28a3
Showing 1 changed file with 47 additions and 19 deletions.
66 changes: 47 additions & 19 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use serde::{Deserialize, Serialize};
use tokio::fs;

use crate::{
manifest::{Dependency, Manifest},
package::PackageStore,
manifest::Manifest,
package::{PackageId, PackageStore},
};

/// The directory used for the generated code
Expand All @@ -37,6 +37,14 @@ impl fmt::Display for Language {
}
}

/// A configuration passed to a generator to compile a package
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct GenerationConfig<'i, 'p> {
pub package: &'i PackageId,
pub location: &'p Path,
pub out: &'p Path,
}

/// Backend used to generate code bindings
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Generator {
Expand All @@ -48,25 +56,24 @@ impl Generator {
pub const TONIC_INCLUDE_FILE: &str = "mod.rs";

/// Run the generator for a dependency and output files into `out`
pub async fn run(&self, dependency: &Dependency, out: &Path) -> eyre::Result<()> {
pub async fn run(&self, config: GenerationConfig<'_, '_>) -> eyre::Result<()> {
let protoc = protoc_bin_path().wrap_err("Unable to locate vendored protoc")?;

std::env::set_var("PROTOC", protoc.clone());

match self {
Generator::Tonic => {
let out = out.join(dependency.package.as_str());
let out = config.out.join(config.package.as_str());

fs::remove_dir_all(&out).await.ok();
fs::remove_dir_all(&out).await.ok();

fs::create_dir_all(&out)
.await
.wrap_err("Failed to recreate dependency output directory")?;
fs::create_dir_all(&out)
.await
.wrap_err("Failed to recreate dependency output directory")?;

let package = PackageStore::locate(&dependency.package);
let protos = PackageStore::collect(&package).await;
match self {
Generator::Tonic => {
let protos = PackageStore::collect(config.location).await;

let includes = &[package];
let includes = &[&config.location];

tonic_build::configure()
.build_client(true)
Expand All @@ -90,8 +97,8 @@ pub async fn generate(language: Language) -> eyre::Result<()> {
tracing::info!(":: initializing code generator for {language}");

eyre::ensure!(
!manifest.dependencies.is_empty(),
"At least one dependency is needed to generate code bindings."
manifest.package.is_some() || !manifest.dependencies.is_empty(),
"Either a local package or at least one dependency is needed to generate code bindings."
);

// Only tonic is supported right now
Expand All @@ -110,15 +117,37 @@ pub async fn generate(language: Language) -> eyre::Result<()> {
out
};

if let Some(ref pkg) = manifest.package {
let location = Path::new(PackageStore::PROTO_PATH);

generator
.run(GenerationConfig {
package: &pkg.name,
location,
out: &out,
})
.await
.wrap_err_with(|| format!("Failed to generate bindings for {}", pkg.name))?;

tracing::info!(":: compiled {} [{}]", pkg.name, location.display());
}

for dependency in manifest.dependencies {
let location = PackageStore::locate(&dependency.package);

generator
.run(&dependency, &out)
.run(GenerationConfig {
package: &dependency.package,
location: &location,
out: &out,
})
.await
.wrap_err_with(|| format!("Failed to generate bindings for {}", dependency.package))?;

tracing::info!(
":: compiled {}",
PackageStore::locate(&dependency.package).display()
":: compiled {} [{}]",
dependency.package,
location.display()
);
}

Expand All @@ -137,7 +166,6 @@ pub async fn generate(language: Language) -> eyre::Result<()> {
#[macro_export]
macro_rules! include {
($package:expr) => {
#[allow(non_snake_case)]
::std::include!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/proto/build/rust/",
Expand Down

0 comments on commit 09f28a3

Please sign in to comment.