Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide commands to support using multiple uniffi packages #1

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Introduce wp_spm_public_module_name uniffi.toml config
  • Loading branch information
crazytonyli committed Dec 18, 2024
commit d537beea26d2f9b9d40e2579ebaad9c6a2f9559d
21 changes: 3 additions & 18 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::env;

use anyhow::Result;
@@ -7,7 +6,7 @@ use clap::{Parser, Subcommand};
use crate::apple_platform::ApplePlatform;
use crate::build::BuildExtensions;
use crate::project::Project;
use crate::spm::SPMResolver;
use crate::spm::*;

#[derive(Parser)]
pub(crate) struct Cli {
@@ -65,20 +64,6 @@ fn build(args: BuildArgs) -> Result<()> {
}

fn generate_package(args: GeneratePackageArgs) -> Result<()> {
let map = args
.package_name_map
.split(',')
.map(|pair| {
let mut iter = pair.split(':');
let key = iter.next().unwrap();
let value = iter.next().unwrap();
(key.to_string(), value.to_string())
})
.collect::<HashMap<String, String>>();

let resolver = SPMResolver {
project: Project::new()?,
cargo_package_to_spm_target_map: map,
};
resolver.generate_swift_package(args.project_name)
let project = Project::new()?;
project.generate_swift_package(args.project_name)
}
36 changes: 26 additions & 10 deletions src/project.rs
Original file line number Diff line number Diff line change
@@ -74,6 +74,14 @@ impl Project {
Ok(uniffi_packages.remove(index))
}

pub fn packages_iter(&self) -> impl Iterator<Item = &UniffiPackage> {
self.package.iter()
}

pub fn package(&self, name: &str) -> Option<&UniffiPackage> {
self.packages_iter().find(|p| p.name == name)
}

pub fn ffi_module_name(&self) -> Result<String> {
self.package.ffi_module_name()
}
@@ -148,16 +156,11 @@ impl UniffiPackage {
}

pub fn ffi_module_name(&self) -> Result<String> {
self.uniffi_toml()?
.get("bindings")
.and_then(|t| t.get("swift"))
.and_then(|t| t.get("ffi_module_name"))
.and_then(|t| t.as_str())
.map(|s| s.to_string())
.context(format!(
"ffi_module_name not found in the uniffi.toml of package {}",
self.name
))
self.uniffi_toml_swift_configuration("ffi_module_name")
}

pub fn public_module_name(&self) -> Result<String> {
self.uniffi_toml_swift_configuration("wp_spm_public_module_name")
}

fn uniffi_toml(&self) -> Result<Table> {
@@ -174,4 +177,17 @@ impl UniffiPackage {
.with_context(|| format!("The uniffi.toml of package {} is invalid", self.name))?;
Ok(table)
}

fn uniffi_toml_swift_configuration(&self, key: &str) -> Result<String> {
self.uniffi_toml()?
.get("bindings")
.and_then(|t| t.get("swift"))
.and_then(|t| t.get(key))
.and_then(|t| t.as_str())
.map(|s| s.to_string())
.context(format!(
"{} not found in the uniffi.toml of package {}",
key, self.name
))
}
}
62 changes: 25 additions & 37 deletions src/spm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::{
collections::HashMap,
fs::File,
io::Write,
path::{Path, PathBuf},
@@ -82,14 +81,13 @@ struct InternalTarget {
dependencies: Vec<String>,
}

pub struct SPMResolver {
pub project: Project,
pub cargo_package_to_spm_target_map: HashMap<String, String>,
pub trait SPMExtension {
fn generate_swift_package(&self, project_name: String) -> Result<()>;
}

impl SPMResolver {
pub fn generate_swift_package(&self, project_name: String) -> Result<()> {
let top_level_package = &self.project.package;
impl SPMExtension for Project {
fn generate_swift_package(&self, project_name: String) -> Result<()> {
let top_level_package = &self.package;

let targets = top_level_package
.iter()
@@ -101,8 +99,8 @@ impl SPMResolver {
.collect::<Result<Vec<_>>>()?;

let template = PackageTemplate {
package_name: self.spm_target_name(&top_level_package.name),
ffi_module_name: self.project.ffi_module_name()?,
package_name: top_level_package.public_module_name()?,
ffi_module_name: self.ffi_module_name()?,
project_name,
targets,
internal_targets,
@@ -122,36 +120,26 @@ impl SPMResolver {

Ok(())
}
}

impl Project {
fn swift_package_manifest_file_path(&self) -> Utf8PathBuf {
self.project
.cargo_metadata
.workspace_root
.join("Package.swift")
}

fn spm_target_name(&self, cargo_package_name: &str) -> String {
self.cargo_package_to_spm_target_map
.get(cargo_package_name)
.unwrap_or_else(|| {
panic!(
"No SPM target name specified for cargo package {}",
cargo_package_name
)
})
.to_string()
self.cargo_metadata.workspace_root.join("Package.swift")
}

fn public_target_name(&self, package: &UniffiPackage) -> String {
self.spm_target_name(&package.name)
fn spm_target_name(&self, cargo_package_name: &str) -> Result<String> {
self.package(cargo_package_name)
.context(format!("Can't find package {}", cargo_package_name))?
.public_module_name()
}

fn internal_target_name(&self, package: &UniffiPackage) -> String {
format!("{}Internal", self.spm_target_name(&package.name))
fn internal_target_name(&self, package: &UniffiPackage) -> Result<String> {
let name = package.public_module_name()?;
Ok(format!("{}Internal", name))
}

fn internal_target(&self, package: &UniffiPackage) -> Result<InternalTarget> {
let swift_wrapper_dir = self.project.swift_wrapper_dir()?;
let swift_wrapper_dir = self.swift_wrapper_dir()?;
let source_file_name = package.swift_wrapper_file_name();
let binding_file = swift_wrapper_dir.join(&source_file_name);
if !binding_file.exists() {
@@ -165,13 +153,13 @@ impl SPMResolver {
.dependencies
.iter()
.map(|p| self.internal_target_name(p))
.collect::<Vec<_>>();
.collect::<Result<Vec<_>>>()?;

Ok(InternalTarget {
name: self.internal_target_name(package),
name: self.internal_target_name(package)?,
swift_wrapper_dir: fs::relative_path(
swift_wrapper_dir,
&self.project.cargo_metadata.workspace_root,
&self.cargo_metadata.workspace_root,
),
source_file: source_file_name,
dependencies,
@@ -186,18 +174,18 @@ impl SPMResolver {
let sources_dir = get_only_subdir(swift_code_dir.join("Sources"))?;
let tests_dir = get_only_subdir(swift_code_dir.join("Tests"))?;

let root_dir = &self.project.cargo_metadata.workspace_root;
let root_dir = &self.cargo_metadata.workspace_root;
let library_source_path = fs::relative_path(&sources_dir, root_dir);
let test_source_path = fs::relative_path(&tests_dir, root_dir);

let dependencies = package
.dependencies
.iter()
.map(|p| self.spm_target_name(&p.name))
.collect();
.collect::<Result<Vec<_>>>()?;

Ok(Target {
name: self.public_target_name(package),
name: package.public_module_name()?,
library_source_path,
test_source_path,
dependencies,
@@ -206,7 +194,7 @@ impl SPMResolver {
}

fn vend_swift_source_code(&self, package: &UniffiPackage) -> Result<Utf8PathBuf> {
let root_dir = &self.project.cargo_metadata.workspace_root;
let root_dir = &self.cargo_metadata.workspace_root;
if !root_dir.is_absolute() {
anyhow::bail!(
"Cargo workspace root dir is not an absolute path: {}",