Skip to content

Commit 17495e7

Browse files
committed
xtask: Add support for building watchOS targets.
1 parent 9ab886f commit 17495e7

File tree

2 files changed

+132
-15
lines changed

2 files changed

+132
-15
lines changed

bindings/matrix-sdk-ffi/build.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ fn setup_x86_64_android_workaround() {
4343
}
4444
}
4545

46+
/// Adds a workaround for watchOS simulator builds to manually link against the
47+
/// CoreFoundation framework in order to avoid linker errors. Otherwise, errors
48+
/// like the following may occur:
49+
///
50+
/// = note: Undefined symbols for architecture arm64:
51+
/// "_CFArrayCreate", referenced from:
52+
/// "_CFDataCreate", referenced from:
53+
/// "_CFRelease", referenced from:
54+
/// etc.
55+
fn setup_watchos_simulator_workaround() {
56+
let target = env::var("TARGET").expect("TARGET not set");
57+
if target.ends_with("watchos-sim") {
58+
println!("cargo:rustc-link-arg=-framework");
59+
println!("cargo:rustc-link-arg=CoreFoundation");
60+
}
61+
}
62+
4663
/// Run the clang binary at `clang_path`, and return its major version number
4764
fn get_clang_major_version(clang_path: &Path) -> String {
4865
let clang_output =
@@ -58,6 +75,7 @@ fn get_clang_major_version(clang_path: &Path) -> String {
5875

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

6381
let git_config = GitclBuilder::default().sha(true).build()?;

xtask/src/swift.rs

Lines changed: 114 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ enum SwiftCommand {
4242
#[clap(long)]
4343
target: Option<Vec<String>>,
4444

45+
/// Includes the Tier 3 targets (such as watchOS) when building all
46+
/// supported targets. Requires a nightly toolchain with the `rust-src`
47+
/// component installed.
48+
#[clap(long)]
49+
tier3_targets: bool,
50+
4551
/// Move the generated xcframework and swift sources into the given
4652
/// components-folder
4753
#[clap(long)]
@@ -54,6 +60,13 @@ enum SwiftCommand {
5460
#[clap(long)]
5561
ios_deployment_target: Option<String>,
5662

63+
/// The wachOS deployment target to use when building the framework.
64+
///
65+
/// Defaults to not being set, which implies that the build will use the
66+
/// default values provided by the Rust and Xcode toolchains.
67+
#[clap(long)]
68+
watchos_deployment_target: Option<String>,
69+
5770
/// Build the targets one by one instead of passing all of them
5871
/// to cargo in one go, which makes it hang on lesser devices like plain
5972
/// Apple Silicon M1s
@@ -72,10 +85,12 @@ impl SwiftArgs {
7285
SwiftCommand::BuildFramework {
7386
release,
7487
profile,
75-
components_path,
7688
target: targets,
77-
sequentially,
89+
tier3_targets,
90+
components_path,
7891
ios_deployment_target,
92+
watchos_deployment_target,
93+
sequentially,
7994
} => {
8095
// The dev profile seems to cause crashes on some platforms so we default to
8196
// reldbg (https://github.com/matrix-org/matrix-rust-sdk/issues/4009)
@@ -84,9 +99,11 @@ impl SwiftArgs {
8499
build_xcframework(
85100
profile,
86101
targets,
102+
tier3_targets,
87103
components_path,
88104
sequentially,
89105
ios_deployment_target.as_deref(),
106+
watchos_deployment_target.as_deref(),
90107
)
91108
}
92109
}
@@ -97,15 +114,26 @@ impl SwiftArgs {
97114
struct Target {
98115
triple: &'static str,
99116
platform: Platform,
117+
status: TargetStatus,
100118
description: &'static str,
101119
}
102120

121+
#[derive(Hash, PartialEq, Eq, Clone)]
122+
enum TargetStatus {
123+
/// A tier 1 or 2 target that can be built with stable Rust.
124+
TopTier,
125+
/// A tier 3 target that requires nightly Rust and `-Zbuild-std`.
126+
Tier3,
127+
}
128+
103129
/// The platform for which a particular target can run on.
104130
#[derive(Hash, PartialEq, Eq, Clone)]
105131
enum Platform {
106132
Macos,
107133
Ios,
108134
IosSimulator,
135+
Watchos,
136+
WatchosSimulator,
109137
}
110138

111139
impl Platform {
@@ -115,6 +143,8 @@ impl Platform {
115143
Platform::Macos => "macOS",
116144
Platform::Ios => "iOS",
117145
Platform::IosSimulator => "iOS Simulator",
146+
Platform::Watchos => "watchOS",
147+
Platform::WatchosSimulator => "watchOS Simulator",
118148
}
119149
}
120150

@@ -125,6 +155,8 @@ impl Platform {
125155
Platform::Macos => "macos",
126156
Platform::Ios => "ios",
127157
Platform::IosSimulator => "ios-simulator",
158+
Platform::Watchos => "watchos",
159+
Platform::WatchosSimulator => "watchos-simulator",
128160
}
129161
}
130162
}
@@ -136,27 +168,60 @@ const FFI_FEATURES: &str = "native-tls,sentry";
136168

137169
/// The list of targets supported by the SDK.
138170
const TARGETS: &[Target] = &[
139-
Target { triple: "aarch64-apple-ios", platform: Platform::Ios, description: "iOS" },
171+
Target {
172+
triple: "aarch64-apple-ios",
173+
platform: Platform::Ios,
174+
status: TargetStatus::TopTier,
175+
description: "iOS",
176+
},
140177
Target {
141178
triple: "aarch64-apple-darwin",
142179
platform: Platform::Macos,
180+
status: TargetStatus::TopTier,
143181
description: "macOS (Apple Silicon)",
144182
},
145183
Target {
146184
triple: "x86_64-apple-darwin",
147185
platform: Platform::Macos,
186+
status: TargetStatus::TopTier,
148187
description: "macOS (Intel)",
149188
},
150189
Target {
151190
triple: "aarch64-apple-ios-sim",
152191
platform: Platform::IosSimulator,
192+
status: TargetStatus::TopTier,
153193
description: "iOS Simulator (Apple Silicon)",
154194
},
155195
Target {
156196
triple: "x86_64-apple-ios",
157197
platform: Platform::IosSimulator,
198+
status: TargetStatus::TopTier,
158199
description: "iOS Simulator (Intel) ",
159200
},
201+
Target {
202+
triple: "aarch64-apple-watchos",
203+
platform: Platform::Watchos,
204+
status: TargetStatus::Tier3,
205+
description: "watchOS (ARM64)",
206+
},
207+
Target {
208+
triple: "arm64_32-apple-watchos",
209+
platform: Platform::Watchos,
210+
status: TargetStatus::Tier3,
211+
description: "watchOS (ARM64_32)",
212+
},
213+
Target {
214+
triple: "aarch64-apple-watchos-sim",
215+
platform: Platform::WatchosSimulator,
216+
status: TargetStatus::Tier3,
217+
description: "watchOS Simulator (ARM64)",
218+
},
219+
Target {
220+
triple: "x86_64-apple-watchos-sim",
221+
platform: Platform::WatchosSimulator,
222+
status: TargetStatus::Tier3,
223+
description: "watchOS Simulator (Intel)",
224+
},
160225
];
161226

162227
fn build_library() -> Result<()> {
@@ -208,9 +273,11 @@ fn generate_uniffi(library_path: &Utf8Path, ffi_directory: &Utf8Path) -> Result<
208273
fn build_xcframework(
209274
profile: &str,
210275
targets: Option<Vec<String>>,
276+
tier3_targets: bool,
211277
components_path: Option<Utf8PathBuf>,
212278
sequentially: bool,
213279
ios_deployment_target: Option<&str>,
280+
watchos_deployment_target: Option<&str>,
214281
) -> Result<()> {
215282
let root_dir = workspace::root_path()?;
216283
let apple_dir = root_dir.join("bindings/apple");
@@ -234,12 +301,19 @@ fn build_xcframework(
234301
TARGETS.iter().find(|target| target.triple == *t).expect("Invalid target specified")
235302
})
236303
.collect()
237-
} else {
304+
} else if tier3_targets {
238305
TARGETS.iter().collect()
306+
} else {
307+
TARGETS.iter().filter(|target| target.status == TargetStatus::TopTier).collect()
239308
};
240309

241-
let platform_build_paths =
242-
build_targets(targets, profile, sequentially, ios_deployment_target)?;
310+
let platform_build_paths = build_targets(
311+
targets,
312+
profile,
313+
sequentially,
314+
ios_deployment_target,
315+
watchos_deployment_target,
316+
)?;
243317
let libs = lipo_platform_libraries(&platform_build_paths, &generated_dir)?;
244318

245319
println!("-- Generating uniffi files");
@@ -309,6 +383,7 @@ fn build_targets(
309383
profile: &str,
310384
sequentially: bool,
311385
ios_deployment_target: Option<&str>,
386+
watchos_deployment_target: Option<&str>,
312387
) -> Result<HashMap<Platform, Vec<Utf8PathBuf>>> {
313388
let sh = sh();
314389

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

323400
if sequentially {
324401
for target in &targets {
325402
let triple = target.triple;
326403

327404
println!("-- Building for {}", target.description);
328-
cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi --target {triple} --profile {profile} --features {FFI_FEATURES}")
329-
.run()?;
405+
if target.status == TargetStatus::TopTier {
406+
cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi --target {triple} --profile {profile} --features {FFI_FEATURES}")
407+
.run()?;
408+
} else {
409+
cmd!(sh, "rustup run nightly cargo build -p matrix-sdk-ffi -Zbuild-std --target {triple} --profile {profile} --features {FFI_FEATURES}")
410+
.run()?;
411+
}
330412
}
331413
} else {
332-
let triples = &targets.iter().map(|target| target.triple).collect::<Vec<_>>();
333-
let mut cmd = cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi");
334-
for triple in triples {
335-
cmd = cmd.arg("--target").arg(triple);
414+
let (stable_targets, tier3_targets): (Vec<&Target>, Vec<&Target>) =
415+
targets.iter().partition(|t| t.status == TargetStatus::TopTier);
416+
417+
if !stable_targets.is_empty() {
418+
let triples = stable_targets.iter().map(|target| target.triple).collect::<Vec<_>>();
419+
let mut cmd = cmd!(sh, "rustup run stable cargo build -p matrix-sdk-ffi");
420+
for triple in &triples {
421+
cmd = cmd.arg("--target").arg(triple);
422+
}
423+
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);
424+
425+
println!("-- Building for {} targets", triples.len());
426+
cmd.run()?;
336427
}
337-
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);
338428

339-
println!("-- Building for {} targets", triples.len());
340-
cmd.run()?;
429+
if !tier3_targets.is_empty() {
430+
let triples = tier3_targets.iter().map(|target| target.triple).collect::<Vec<_>>();
431+
let mut cmd = cmd!(sh, "rustup run nightly cargo build -p matrix-sdk-ffi -Zbuild-std");
432+
for triple in &triples {
433+
cmd = cmd.arg("--target").arg(triple);
434+
}
435+
cmd = cmd.arg("--profile").arg(profile).arg("--features").arg(FFI_FEATURES);
436+
437+
println!("-- Building for {} targets with nightly -Zbuild-std", triples.len());
438+
cmd.run()?;
439+
}
341440
}
342441

343442
// a hashmap of platform to array, where each array contains all the paths for

0 commit comments

Comments
 (0)