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

Configuration support evolves - 1/n #13

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ categories = ["development-tools::cargo-plugins", "development-tools::ffi"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4.0", features = ["derive"] }
anyhow = "1.0"
cargo_metadata = { version = "0.18", features = ["builder"] }
cargo_metadata = { version = "*", features = ["builder"] }
camino = "1.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand All @@ -27,6 +26,15 @@ zip-extensions = "0.6"
fs_extra = "1.2"
xshell = "0.2.6"
glob = "0.3.1"
toml = "0.8.14"
serde-aux = "4.5.0"
log = "0.4"

clap = { version = "4.0", features = ["derive"] }
clap-cargo = { version = "0.14", features = ["cargo_metadata"] }

[patch.crates-io]
cargo_metadata = { git = "https://github.com/Binlogo/cargo_metadata.git", branch = "op/target-kind-check" }

[dev-dependencies]
tempfile = "3.3"
Expand Down
73 changes: 73 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
### Configuration Reference (Draft)

#### Overview

This document provides the structure and descriptions of the configuration used by `cargo-xcframework` to bundle an XCFramework for multiple platforms. The configuration is specified in a TOML file (`xcframework.toml` or within `Cargo.toml` under `[package.metadata.xcframework]`).

#### Example Configuration

```toml
# Example xcframework.toml

name = "ExampleFramework"

[platforms]
ios = { simulator = false, archs = ["aarch64", "x86_64"] }
macos = {} # use default platform configuration

header_paths = ["/path/to/header1.h", "/path/to/header2.h"]
module_paths = ["/path/to/module.modulemap"]
output_dir = "/path/to/output"
```

#### Configuration Fields

- `name` (optional, string): The name of the XCFramework.

##### Platforms

Defines the target platforms and their specific configurations. Platforms can either have detailed configurations or use default values by simply specifying the platform name.

- `platforms` (required, mixed table):
- `<os>` (table | string): If specified as a table, it includes specific configurations. If specified as a string, it uses the default configuration for the platform.
- `simulator` (optional, boolean): Whether to enable building for the simulator. Defaults to `true`.
- Note: This field is only applicable to the targets with `-sim` supported, e.g: `ios` .
- `archs` (required, array of strings): Architectures to enable for the target platform.

###### Supported Platforms

- `ios`: iOS platform.
- Default targets:
- `aarch64-apple-ios`, `x86_64-apple-ios` and `aarch64-apple-ios-sim`
- `macos`: macOS platform.
- Default targets: `x86_64-apple-darwin`, `aarch64-apple-darwin`.
- More platforms will be supported in the future. (Contributions are welcome!)

Under the hood, all the platforms are mapped to the corresponding `cargo` targets. For example, `ios` is mapped to `aarch64-apple-ios` and `x86_64-apple-ios`, `aarch64-apple-ios-sim` targets, respond to configurations for the iOS platform.

> Reference: [Rust Platform Support](https://doc.rust-lang.org/rustc/platform-support.html)

##### Example

```toml
[platforms]
ios = { simulator = false, archs = ["aarch64", "x86_64"] }
macos = {} # use default platform configuration
```

##### Paths

Defines paths to additional resources required for building the XCFramework.

- `header_paths` (optional, array of strings): Paths to header files needed for the build.
- `module_paths` (optional, array of strings): Paths to module files needed for the build.
- `output_dir` (optional, string): Directory where the output will be stored.
- Note: If not specified, the output will be stored in the `target/xcframework` directory.

##### Example

```toml
header_paths = ["/path/to/header1", "/path/to/header2"]
module_paths = ["/path/to/module1", "/path/to/module2"]
output_dir = "/path/to/output"
```
3 changes: 1 addition & 2 deletions examples/end-to-end/mymath-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ crate-type = ["staticlib", "cdylib"]
[package.metadata.xcframework]
lib-type = "staticlib"
include-dir = "include"
iOS = true
iOS = { simulator = true }
macOS = true
simulators = true

[profile.release]
lto = true
Expand Down
2 changes: 1 addition & 1 deletion examples/end-to-end/swift-exe/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let package = Package(
dependencies: ["MyMath"]),
.binaryTarget(
name: "MyMath",
path: "../mymath-lib/target/MyMath.xcframework.zip"
path: "../mymath-lib/target/MyMath.xcframework"
),
]
)
8 changes: 0 additions & 8 deletions examples/multi-platform/mymath-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ edition = "2021"
name = "mymath"
crate-type = ["staticlib", "cdylib"]

[package.metadata.xcframework]
lib-type = "staticlib"
include-dir = "include"
iOS = true
macOS = true
simulators = true
zip = false

[profile.release]
lto = true
opt-level = 'z'
Expand Down
9 changes: 9 additions & 0 deletions examples/multi-platform/mymath-lib/xcframework.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "MyMath"
lib-type = "cdylib"
header_paths = ["include/mymath.h"]
module_paths = ["include/module.modulemap"]
output_dir = "../tuist-workspace/Shared"

[platforms]
ios = {}
macos = true
4 changes: 3 additions & 1 deletion examples/multi-platform/mymath-lib/xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ edition = "2021"

[dependencies]
anyhow = "*"
xcframework = { path = "../../../.." }
clap = { version = "4.5.7", features = ["derive"] }
clap-cargo = { version = "0.14.0", features = ["cargo_metadata"] }
xcframework = { path = "../../../.." }
112 changes: 90 additions & 22 deletions examples/multi-platform/mymath-lib/xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,93 @@
use anyhow::{Context, Result};
use anyhow::Context;
use anyhow::Result;
use clap::{Parser, Subcommand};

#[derive(Parser)]
struct Xtask {
#[clap(subcommand)]
cmd: Command,
}

#[derive(Subcommand)]
enum Command {
BuildXcframework(XcframeworkArgs),
}

#[derive(Debug, Clone, clap::Args)]
pub struct XcframeworkArgs {
#[command(flatten)]
manifest: clap_cargo::Manifest,
}

impl XcframeworkArgs {
fn run(&self) -> Result<()> {
let metadata = self.manifest.metadata().exec()?;
let pkg = metadata.root_package().context("No root package")?;
let config = xcframework::config::load_package_config(pkg)?;

println!("{:#?}", config);

let lib_name = "mymath";
let pkg = &pkg.name;
let profile = "release";

let name = "MyMath";
let targets = config.targets();
let lib_type = &config.lib_type;
let sequentially = false;

let libs_dir = metadata.target_directory.join("libs");
std::fs::create_dir_all(&libs_dir)?;

let platform_lib_paths = xcframework::core::build::build_targets(
pkg,
lib_name,
profile,
lib_type,
targets,
sequentially,
)?;

let libs = xcframework::core::lipo_create_platform_libraries(
&platform_lib_paths,
name,
&libs_dir,
)?;

let header_paths = config.header_paths;
let module_paths = config.module_paths;
let frameworks_dir = metadata.target_directory.join("frameworks");
std::fs::create_dir_all(&frameworks_dir)?;

let framework_paths = libs
.into_iter()
.map(|(platform, lib_path)| {
std::fs::create_dir_all(&frameworks_dir)?;

xcframework::core::wrap_as_framework(
platform,
lib_type,
&lib_path,
&header_paths,
&module_paths,
name,
&frameworks_dir,
)
})
.collect::<anyhow::Result<Vec<_>>>()?;

let output_dir = metadata.target_directory.join("xcframeworks");
let xcframework_path =
xcframework::core::create_xcframework(framework_paths, name, &output_dir)?;

println!("✅ Created XCFramework at {:?}", xcframework_path);

Ok(())
}
}

fn main() -> Result<()> {
// TODO: complete cargo-xtask usage example

let cli = xcframework::XcCli {
lib_type: None,
quiet: false,
package: None,
verbose: 0,
unstable_flags: None,
release: false,
profile: None,
features: vec![],
all_features: false,
no_default_features: false,
target_dir: None,
manifest_path: None,
};
let produced = xcframework::build(cli).context("building with xcframework")?;

println!("produced: {:?}", produced);

Ok(())
match Xtask::parse().cmd {
Command::BuildXcframework(xcframework) => xcframework.run(),
}
}
Loading
Loading