Skip to content
Merged
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
18 changes: 18 additions & 0 deletions bindings/matrix-sdk-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ fn setup_x86_64_android_workaround() {
}
}

/// Adds a workaround for watchOS simulator builds to manually link against the
/// CoreFoundation framework in order to avoid linker errors. Otherwise, errors
/// like the following may occur:
///
/// = note: Undefined symbols for architecture arm64:
/// "_CFArrayCreate", referenced from:
/// "_CFDataCreate", referenced from:
/// "_CFRelease", referenced from:
/// etc.
fn setup_watchos_simulator_workaround() {
let target = env::var("TARGET").expect("TARGET not set");
if target.ends_with("watchos-sim") {
println!("cargo:rustc-link-arg=-framework");
println!("cargo:rustc-link-arg=CoreFoundation");
}
}

/// Run the clang binary at `clang_path`, and return its major version number
fn get_clang_major_version(clang_path: &Path) -> String {
let clang_output =
Expand All @@ -58,6 +75,7 @@ fn get_clang_major_version(clang_path: &Path) -> String {

fn main() -> Result<(), Box<dyn Error>> {
setup_x86_64_android_workaround();
setup_watchos_simulator_workaround();
uniffi::generate_scaffolding("./src/api.udl").expect("Building the UDL file failed");

let git_config = GitclBuilder::default().sha(true).build()?;
Expand Down
129 changes: 114 additions & 15 deletions xtask/src/swift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ enum SwiftCommand {
#[clap(long)]
target: Option<Vec<String>>,

/// Includes the Tier 3 targets (such as watchOS) when building all
/// supported targets. Requires a nightly toolchain with the `rust-src`
/// component installed.
#[clap(long)]
tier3_targets: bool,

/// Move the generated xcframework and swift sources into the given
/// components-folder
#[clap(long)]
Expand All @@ -54,6 +60,13 @@ enum SwiftCommand {
#[clap(long)]
ios_deployment_target: Option<String>,

/// The wachOS deployment target to use when building the framework.
///
/// Defaults to not being set, which implies that the build will use the
/// default values provided by the Rust and Xcode toolchains.
#[clap(long)]
watchos_deployment_target: Option<String>,

/// Build the targets one by one instead of passing all of them
/// to cargo in one go, which makes it hang on lesser devices like plain
/// Apple Silicon M1s
Expand All @@ -72,10 +85,12 @@ impl SwiftArgs {
SwiftCommand::BuildFramework {
release,
profile,
components_path,
target: targets,
sequentially,
tier3_targets,
components_path,
ios_deployment_target,
watchos_deployment_target,
sequentially,
} => {
// The dev profile seems to cause crashes on some platforms so we default to
// reldbg (https://github.com/matrix-org/matrix-rust-sdk/issues/4009)
Expand All @@ -84,9 +99,11 @@ impl SwiftArgs {
build_xcframework(
profile,
targets,
tier3_targets,
components_path,
sequentially,
ios_deployment_target.as_deref(),
watchos_deployment_target.as_deref(),
)
}
}
Expand All @@ -97,15 +114,26 @@ impl SwiftArgs {
struct Target {
triple: &'static str,
platform: Platform,
status: TargetStatus,
description: &'static str,
}

#[derive(Hash, PartialEq, Eq, Clone)]
enum TargetStatus {
/// A tier 1 or 2 target that can be built with stable Rust.
TopTier,
/// A tier 3 target that requires nightly Rust and `-Zbuild-std`.
Tier3,
}

/// The platform for which a particular target can run on.
#[derive(Hash, PartialEq, Eq, Clone)]
enum Platform {
Macos,
Ios,
IosSimulator,
Watchos,
WatchosSimulator,
}

impl Platform {
Expand All @@ -115,6 +143,8 @@ impl Platform {
Platform::Macos => "macOS",
Platform::Ios => "iOS",
Platform::IosSimulator => "iOS Simulator",
Platform::Watchos => "watchOS",
Platform::WatchosSimulator => "watchOS Simulator",
}
}

Expand All @@ -125,6 +155,8 @@ impl Platform {
Platform::Macos => "macos",
Platform::Ios => "ios",
Platform::IosSimulator => "ios-simulator",
Platform::Watchos => "watchos",
Platform::WatchosSimulator => "watchos-simulator",
}
}
}
Expand All @@ -136,27 +168,60 @@ const FFI_FEATURES: &str = "native-tls,sentry";

/// The list of targets supported by the SDK.
const TARGETS: &[Target] = &[
Target { triple: "aarch64-apple-ios", platform: Platform::Ios, description: "iOS" },
Target {
triple: "aarch64-apple-ios",
platform: Platform::Ios,
status: TargetStatus::TopTier,
description: "iOS",
},
Target {
triple: "aarch64-apple-darwin",
platform: Platform::Macos,
status: TargetStatus::TopTier,
description: "macOS (Apple Silicon)",
},
Target {
triple: "x86_64-apple-darwin",
platform: Platform::Macos,
status: TargetStatus::TopTier,
description: "macOS (Intel)",
},
Target {
triple: "aarch64-apple-ios-sim",
platform: Platform::IosSimulator,
status: TargetStatus::TopTier,
description: "iOS Simulator (Apple Silicon)",
},
Target {
triple: "x86_64-apple-ios",
platform: Platform::IosSimulator,
status: TargetStatus::TopTier,
description: "iOS Simulator (Intel) ",
},
Target {
triple: "aarch64-apple-watchos",
platform: Platform::Watchos,
status: TargetStatus::Tier3,
description: "watchOS (ARM64)",
},
Target {
triple: "arm64_32-apple-watchos",
platform: Platform::Watchos,
status: TargetStatus::Tier3,
description: "watchOS (ARM64_32)",
},
Target {
triple: "aarch64-apple-watchos-sim",
platform: Platform::WatchosSimulator,
status: TargetStatus::Tier3,
description: "watchOS Simulator (ARM64)",
},
Target {
triple: "x86_64-apple-watchos-sim",
platform: Platform::WatchosSimulator,
status: TargetStatus::Tier3,
description: "watchOS Simulator (Intel)",
},
];

fn build_library() -> Result<()> {
Expand Down Expand Up @@ -208,9 +273,11 @@ fn generate_uniffi(library_path: &Utf8Path, ffi_directory: &Utf8Path) -> Result<
fn build_xcframework(
profile: &str,
targets: Option<Vec<String>>,
tier3_targets: bool,
components_path: Option<Utf8PathBuf>,
sequentially: bool,
ios_deployment_target: Option<&str>,
watchos_deployment_target: Option<&str>,
) -> Result<()> {
let root_dir = workspace::root_path()?;
let apple_dir = root_dir.join("bindings/apple");
Expand All @@ -234,12 +301,19 @@ fn build_xcframework(
TARGETS.iter().find(|target| target.triple == *t).expect("Invalid target specified")
})
.collect()
} else {
} else if tier3_targets {
TARGETS.iter().collect()
} else {
TARGETS.iter().filter(|target| target.status == TargetStatus::TopTier).collect()
};

let platform_build_paths =
build_targets(targets, profile, sequentially, ios_deployment_target)?;
let platform_build_paths = build_targets(
targets,
profile,
sequentially,
ios_deployment_target,
watchos_deployment_target,
)?;
let libs = lipo_platform_libraries(&platform_build_paths, &generated_dir)?;

println!("-- Generating uniffi files");
Expand Down Expand Up @@ -309,6 +383,7 @@ fn build_targets(
profile: &str,
sequentially: bool,
ios_deployment_target: Option<&str>,
watchos_deployment_target: Option<&str>,
) -> Result<HashMap<Platform, Vec<Utf8PathBuf>>> {
let sh = sh();

Expand All @@ -319,25 +394,49 @@ fn build_targets(
let _env_guard2 = sh.push_env("AARCH64_APPLE_IOS_CC", "/usr/bin/clang");
let _env_guard3 =
ios_deployment_target.map(|target| sh.push_env("IPHONEOS_DEPLOYMENT_TARGET", target));
let _env_guard4 =
watchos_deployment_target.map(|target| sh.push_env("WATCHOS_DEPLOYMENT_TARGET", target));

if sequentially {
for target in &targets {
let triple = target.triple;

println!("-- Building for {}", target.description);
cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi --target {triple} --profile {profile} --features {FFI_FEATURES}")
.run()?;
if target.status == TargetStatus::TopTier {
cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi --target {triple} --profile {profile} --features {FFI_FEATURES}")
.run()?;
} else {
cmd!(sh, "rustup run nightly cargo build -p matrix-sdk-ffi -Zbuild-std --target {triple} --profile {profile} --features {FFI_FEATURES}")
.run()?;
}
}
} else {
let triples = &targets.iter().map(|target| target.triple).collect::<Vec<_>>();
let mut cmd = cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi");
for triple in triples {
cmd = cmd.arg("--target").arg(triple);
let (stable_targets, tier3_targets): (Vec<&Target>, Vec<&Target>) =
targets.iter().partition(|t| t.status == TargetStatus::TopTier);

if !stable_targets.is_empty() {
let triples = stable_targets.iter().map(|target| target.triple).collect::<Vec<_>>();
let mut cmd = cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi");
for triple in &triples {
cmd = cmd.arg("--target").arg(triple);
}
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);

println!("-- Building for {} targets", triples.len());
cmd.run()?;
}
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);

println!("-- Building for {} targets", triples.len());
cmd.run()?;
if !tier3_targets.is_empty() {
let triples = tier3_targets.iter().map(|target| target.triple).collect::<Vec<_>>();
let mut cmd = cmd!(sh, "rustup run nightly cargo build -p matrix-sdk-ffi -Zbuild-std");
for triple in &triples {
cmd = cmd.arg("--target").arg(triple);
}
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);

println!("-- Building for {} targets with nightly -Zbuild-std", triples.len());
cmd.run()?;
}
}

// a hashmap of platform to array, where each array contains all the paths for
Expand Down
Loading