final 0.7 fixes: xcode 15/16 hybrid, auto openssldir for android, include_*! tracking hotpatch, fix /assets/ brick at high opt levels, windows linker file, etc (#4376)

* wip: openssl autodetection

* add voltaile read inside of asset fn

* support xcode 15 for --device

* vendor openssl on android

* Smaller width TUI

* switch to anyhow for the entire CLI

* add backtrace and print double printing of cargo_metadata errors

* add some padding to multi-line anyhow error

* check semvers

* don't open if not interactive

* set the tailwind current_dir so it doesn't twitch

* get the oboe demo working

* copy the c++ library on android

* cleanup env vars

* add depinfo watcher

* fix stale hotpatches and crate count

* add musl support

* remove outdated autofmt test

* update scanner app

* add hotdog app and bundle to ci

* upload dx on every branch

* collapse mobile into desktop

* `dx doctor` command

* windows command files

* no pipe on doctor

* fix ci?

* fix links

* fix ci

* use main instead of nightly

* bump node

* build cli for host

* cargo doc

* prep dog_app for bundle

* package hotdog

* no bundle or nightly cli

* comment out nightly cli

* add quotes to linker files
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-07-14 12:54:15 -07:00
1 parent 97947b169b
commit 727752a965
78 files changed
+2270 -817

No files matched your search

+67 -29
View File
@@ -2,7 +2,7 @@ use crate::{
serve::WebServer, BuildArtifacts, BuildRequest, BuildStage, BuilderUpdate, Platform,
ProgressRx, ProgressTx, Result, StructuredOutput,
};
use anyhow::Context;
use anyhow::{bail, Context};
use dioxus_cli_opt::process_file_to;
use futures_util::{future::OptionFuture, pin_mut, FutureExt};
use itertools::Itertools;
@@ -122,25 +122,13 @@ impl AppBuilder {
/// updates (e.g., `wait`, `finish_build`).
/// - The build process is designed to be cancellable and restartable using methods like `abort_all`
/// or `rebuild`.
pub(crate) fn start(request: &BuildRequest, mode: BuildMode) -> Result<Self> {
pub(crate) fn new(request: &BuildRequest) -> Result<Self> {
let (tx, rx) = futures_channel::mpsc::unbounded();
Ok(Self {
build: request.clone(),
stage: BuildStage::Initializing,
build_task: tokio::spawn({
let request = request.clone();
let tx = tx.clone();
async move {
let ctx = BuildContext {
mode,
tx: tx.clone(),
};
request.verify_tooling(&ctx).await?;
request.prepare_build_dir()?;
request.build(&ctx).await
}
}),
build_task: tokio::task::spawn(std::future::pending()),
tx,
rx,
patches: vec![],
@@ -164,6 +152,29 @@ impl AppBuilder {
})
}
/// Create a new `AppBuilder` and immediately start a build process.
pub fn started(request: &BuildRequest, mode: BuildMode) -> Result<Self> {
let mut builder = Self::new(request)?;
builder.start(mode);
Ok(builder)
}
pub(crate) fn start(&mut self, mode: BuildMode) {
self.build_task = tokio::spawn({
let request = self.build.clone();
let tx = self.tx.clone();
async move {
let ctx = BuildContext {
mode,
tx: tx.clone(),
};
request.verify_tooling(&ctx).await?;
request.prepare_build_dir()?;
request.build(&ctx).await
}
});
}
/// Wait for any new updates to the builder - either it completed or gave us a message etc
pub(crate) async fn wait(&mut self) -> BuilderUpdate {
use futures_util::StreamExt;
@@ -178,7 +189,7 @@ impl AppBuilder {
match bundle {
Ok(Ok(bundle)) => BuilderUpdate::BuildReady { bundle },
Ok(Err(err)) => BuilderUpdate::BuildFailed { err },
Err(err) => BuilderUpdate::BuildFailed { err: crate::Error::Runtime(format!("Build panicked! {:#?}", err)) },
Err(err) => BuilderUpdate::BuildFailed { err: anyhow::anyhow!("Build panicked! {:#?}", err) },
}
},
Some(Ok(Some(msg))) = OptionFuture::from(self.stdout.as_mut().map(|f| f.next_line())) => {
@@ -596,8 +607,12 @@ impl AppBuilder {
let triple = self.build.triple.clone();
let asset_dir = self.build.asset_dir();
// Hotpatch asset!() calls
for bundled in res.assets.assets() {
let original_artifacts = self.artifacts.as_mut().unwrap();
let original_artifacts = self
.artifacts
.as_mut()
.context("No artifacts to hotpatch")?;
if original_artifacts.assets.contains(bundled) {
continue;
@@ -623,6 +638,18 @@ impl AppBuilder {
}
}
// Make sure to add `include!()` calls to the watcher so we can watch changes as they evolve
for file in res.depinfo.files.iter() {
let original_artifacts = self
.artifacts
.as_mut()
.context("No artifacts to hotpatch")?;
if !original_artifacts.depinfo.files.contains(file) {
original_artifacts.depinfo.files.push(file.clone());
}
}
tracing::debug!("Patching {} -> {}", original.display(), new.display());
let mut jump_table = crate::build::create_jump_table(&new, &triple, cache)?;
@@ -891,7 +918,7 @@ impl AppBuilder {
.context("Failed to parse xcrun output")?;
let device_uuid = json["result"]["devices"][0]["identifier"]
.as_str()
.ok_or("Failed to extract device UUID")?
.context("Failed to extract device UUID")?
.to_string();
Ok(device_uuid)
@@ -918,14 +945,14 @@ impl AppBuilder {
.await?;
if !output.status.success() {
return Err(format!("Failed to install app: {:?}", output).into());
bail!("Failed to install app: {:?}", output);
}
let json: Value = serde_json::from_str(&std::fs::read_to_string(tmpfile.path())?)
.context("Failed to parse xcrun output")?;
let installation_url = json["result"]["installedApplications"][0]["installationURL"]
.as_str()
.ok_or("Failed to extract installation URL")?
.context("Failed to extract installation URL from xcrun output")?
.to_string();
Ok(installation_url)
@@ -953,7 +980,7 @@ impl AppBuilder {
.await?;
if !output.status.success() {
return Err(format!("Failed to launch app: {:?}", output).into());
bail!("Failed to launch app: {:?}", output);
}
let json: Value = serde_json::from_str(&std::fs::read_to_string(tmpfile.path())?)
@@ -961,7 +988,7 @@ impl AppBuilder {
let status_pid = json["result"]["process"]["processIdentifier"]
.as_u64()
.ok_or("Failed to extract process identifier")?;
.context("Failed to extract process identifier")?;
let output = Command::new("xcrun")
.args([
@@ -978,7 +1005,7 @@ impl AppBuilder {
.await?;
if !output.status.success() {
return Err(format!("Failed to resume app: {:?}", output).into());
bail!("Failed to resume app: {:?}", output);
}
Ok(())
@@ -998,18 +1025,27 @@ To accept the agreement, go to https://developer.apple.com/account
To create a provisioning profile, follow the instructions here:
https://developer.apple.com/documentation/xcode/sharing-your-teams-signing-certificates"#;
let profiles_folder = dirs::home_dir()
// Check the xcode 16 location first
let mut profiles_folder = dirs::home_dir()
.context("Your machine has no home-dir")?
.join("Library/Developer/Xcode/UserData/Provisioning Profiles");
// If it doesn't exist, check the old location
if !profiles_folder.exists() {
profiles_folder = dirs::home_dir()
.context("Your machine has no home-dir")?
.join("Library/MobileDevice/Provisioning Profiles");
}
if !profiles_folder.exists() || profiles_folder.read_dir()?.next().is_none() {
tracing::error!(
r#"No provisioning profiles found when trying to codesign the app.
We checked the folder: {}
We checked the folders:
- XCode16: ~/Library/Developer/Xcode/UserData/Provisioning Profiles
- XCode15: ~/Library/MobileDevice/Provisioning Profiles
{CODESIGN_ERROR}
"#,
profiles_folder.display()
"#
)
}
@@ -1125,8 +1161,10 @@ We checked the folder: {}
.context("Failed to codesign the app")?;
if !output.status.success() {
let stderr = String::from_utf8(output.stderr).unwrap_or_default();
return Err(format!("Failed to codesign the app: {stderr}").into());
bail!(
"Failed to codesign the app: {}",
String::from_utf8(output.stderr).unwrap_or_default()
);
}
Ok(())