feat: copy frameworks to Frameworks folder, detect linkers, custom target dirs (#4174)
* feat: copy frameworks to Frameworks folder * add dylib linking to patching * remove logging * rename __aslr_offset * fix android/linux * support linker flavor * support custom target dirs * custom cargo target dir support * whoops ios * dlsym doesn't exist on windows * look for the right main symbol per platform * distinction between mains * export main on windows * enbable rlib caching * add dx hash * adjust linking warnings * update tui with hotreload state * implement symbol flags * add flags * only run ranlib on darwin * enable lld * paths * add harness test for tls * wip: revert launch mobile * wip * fix fullstack mobile * fix a few bugs - long paths? - reverting back to original * pass-thru fuse-ld args * fix nan in render, fix empty archives * consider existing dep files if archive exists * fmt * drop msrv
This commit is contained in:
1 parent
751f1920c3
commit
0982c1ff8b
25 files changed
+1044
-315
No files matched your search
+261
-107
@@ -1,3 +1,228 @@
|
||||
// use crate::Config;
|
||||
// use crate::{
|
||||
// app::App,
|
||||
// ipc::{IpcMethod, UserWindowEvent},
|
||||
// };
|
||||
// use dioxus_core::*;
|
||||
// use dioxus_document::eval;
|
||||
// use std::any::Any;
|
||||
// use tao::event::{Event, StartCause, WindowEvent};
|
||||
|
||||
// /// Launches the WebView and runs the event loop
|
||||
// pub fn launch(root: fn() -> Element) {
|
||||
// launch_cfg(root, vec![], vec![]);
|
||||
// }
|
||||
|
||||
// /// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
// pub fn launch_cfg(
|
||||
// root: fn() -> Element,
|
||||
// contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
// platform_config: Vec<Box<dyn Any>>,
|
||||
// ) {
|
||||
// let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
// for context in contexts {
|
||||
// virtual_dom.insert_any_root_context(context());
|
||||
// }
|
||||
|
||||
// let platform_config = *platform_config
|
||||
// .into_iter()
|
||||
// .find_map(|cfg| cfg.downcast::<Config>().ok())
|
||||
// .unwrap_or_default();
|
||||
|
||||
// launch_virtual_dom(virtual_dom, platform_config)
|
||||
// }
|
||||
|
||||
// /// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
// pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
|
||||
// #[cfg(feature = "tokio_runtime")]
|
||||
// {
|
||||
// tokio::runtime::Builder::new_multi_thread()
|
||||
// .enable_all()
|
||||
// .build()
|
||||
// .unwrap()
|
||||
// .block_on(tokio::task::unconstrained(async move {
|
||||
// launch_virtual_dom_blocking(virtual_dom, desktop_config)
|
||||
// }));
|
||||
|
||||
// unreachable!("The desktop launch function will never exit")
|
||||
// }
|
||||
|
||||
// #[cfg(not(feature = "tokio_runtime"))]
|
||||
// {
|
||||
// launch_virtual_dom_blocking(virtual_dom, desktop_config);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Launch the WebView and run the event loop, with configuration and root props.
|
||||
// ///
|
||||
// /// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
||||
// /// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
||||
// pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, mut desktop_config: Config) -> ! {
|
||||
// let mut custom_event_handler = desktop_config.custom_event_handler.take();
|
||||
// let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
|
||||
|
||||
// event_loop.run(move |window_event, event_loop, control_flow| {
|
||||
// // Set the control flow and check if any events need to be handled in the app itself
|
||||
// app.tick(&window_event);
|
||||
|
||||
// if let Some(ref mut f) = custom_event_handler {
|
||||
// f(&window_event, event_loop)
|
||||
// }
|
||||
|
||||
// match window_event {
|
||||
// Event::NewEvents(StartCause::Init) => app.handle_start_cause_init(),
|
||||
// Event::LoopDestroyed => app.handle_loop_destroyed(),
|
||||
// Event::WindowEvent {
|
||||
// event, window_id, ..
|
||||
// } => match event {
|
||||
// WindowEvent::CloseRequested => app.handle_close_requested(window_id),
|
||||
// WindowEvent::Destroyed { .. } => app.window_destroyed(window_id),
|
||||
// WindowEvent::Resized(new_size) => app.resize_window(window_id, new_size),
|
||||
// _ => {}
|
||||
// },
|
||||
|
||||
// Event::UserEvent(event) => match event {
|
||||
// UserWindowEvent::Poll(id) => app.poll_vdom(id),
|
||||
// UserWindowEvent::NewWindow => app.handle_new_window(),
|
||||
// UserWindowEvent::CloseWindow(id) => app.handle_close_msg(id),
|
||||
// UserWindowEvent::Shutdown => app.control_flow = tao::event_loop::ControlFlow::Exit,
|
||||
|
||||
// #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||
// UserWindowEvent::GlobalHotKeyEvent(evnt) => app.handle_global_hotkey(evnt),
|
||||
|
||||
// #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||
// UserWindowEvent::MudaMenuEvent(evnt) => app.handle_menu_event(evnt),
|
||||
|
||||
// #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||
// UserWindowEvent::TrayMenuEvent(evnt) => app.handle_tray_menu_event(evnt),
|
||||
|
||||
// #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||
// UserWindowEvent::TrayIconEvent(evnt) => app.handle_tray_icon_event(evnt),
|
||||
|
||||
// #[cfg(all(feature = "devtools", debug_assertions))]
|
||||
// UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
|
||||
|
||||
// // Windows-only drag-n-drop fix events. We need to call the interpreter drag-n-drop code.
|
||||
// UserWindowEvent::WindowsDragDrop(id) => {
|
||||
// if let Some(webview) = app.webviews.get(&id) {
|
||||
// webview.dom.in_runtime(|| {
|
||||
// ScopeId::ROOT.in_runtime(|| {
|
||||
// eval("window.interpreter.handleWindowsDragDrop();");
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// UserWindowEvent::WindowsDragLeave(id) => {
|
||||
// if let Some(webview) = app.webviews.get(&id) {
|
||||
// webview.dom.in_runtime(|| {
|
||||
// ScopeId::ROOT.in_runtime(|| {
|
||||
// eval("window.interpreter.handleWindowsDragLeave();");
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// UserWindowEvent::WindowsDragOver(id, x_pos, y_pos) => {
|
||||
// if let Some(webview) = app.webviews.get(&id) {
|
||||
// webview.dom.in_runtime(|| {
|
||||
// ScopeId::ROOT.in_runtime(|| {
|
||||
// let e = eval(
|
||||
// r#"
|
||||
// const xPos = await dioxus.recv();
|
||||
// const yPos = await dioxus.recv();
|
||||
// window.interpreter.handleWindowsDragOver(xPos, yPos)
|
||||
// "#,
|
||||
// );
|
||||
|
||||
// _ = e.send(x_pos);
|
||||
// _ = e.send(y_pos);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// UserWindowEvent::Ipc { id, msg } => match msg.method() {
|
||||
// IpcMethod::Initialize => app.handle_initialize_msg(id),
|
||||
// IpcMethod::FileDialog => app.handle_file_dialog_msg(msg, id),
|
||||
// IpcMethod::UserEvent => {}
|
||||
// IpcMethod::Query => app.handle_query_msg(msg, id),
|
||||
// IpcMethod::BrowserOpen => app.handle_browser_open(msg),
|
||||
// IpcMethod::Other(_) => {}
|
||||
// },
|
||||
// },
|
||||
// _ => {}
|
||||
// }
|
||||
|
||||
// *control_flow = app.control_flow;
|
||||
// })
|
||||
// }
|
||||
|
||||
// /// Expose the `Java_dev_dioxus_main_WryActivity_create` function to the JNI layer.
|
||||
// /// We hardcode these to have a single trampoline for host Java code to call into.
|
||||
// ///
|
||||
// /// This saves us from having to plumb the top-level package name all the way down into
|
||||
// /// this file. This is better for modularity (ie just call dioxus' main to run the app) as
|
||||
// /// well as cache thrashing since this crate doesn't rely on external env vars.
|
||||
// ///
|
||||
// /// The CLI is expecting to find `dev.dioxus.main` in the final library. If you find a need to
|
||||
// /// change this, you'll need to change the CLI as well.
|
||||
// #[cfg(target_os = "android")]
|
||||
// #[no_mangle]
|
||||
// #[inline(never)]
|
||||
// pub extern "C" fn start_app() {
|
||||
// wry::android_binding!(dev_dioxus, main, wry);
|
||||
// tao::android_binding!(
|
||||
// dev_dioxus,
|
||||
// main,
|
||||
// WryActivity,
|
||||
// wry::android_setup,
|
||||
// dioxus_main_root_fn,
|
||||
// tao
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[cfg(target_os = "android")]
|
||||
// #[doc(hidden)]
|
||||
// pub fn dioxus_main_root_fn() {
|
||||
// // we're going to find the `main` symbol using dlsym directly and call it
|
||||
// unsafe {
|
||||
// let mut main_fn_ptr = libc::dlsym(libc::RTLD_DEFAULT, b"main\0".as_ptr() as _);
|
||||
|
||||
// if main_fn_ptr.is_null() {
|
||||
// main_fn_ptr = libc::dlsym(libc::RTLD_DEFAULT, b"_main\0".as_ptr() as _);
|
||||
// }
|
||||
|
||||
// if main_fn_ptr.is_null() {
|
||||
// panic!("Failed to find main symbol");
|
||||
// }
|
||||
|
||||
// // Set the env vars that rust code might expect, passed off to us by the android app
|
||||
// // Doing this before main emulates the behavior of a regular executable
|
||||
// if cfg!(target_os = "android") && cfg!(debug_assertions) {
|
||||
// load_env_file_from_session_cache();
|
||||
// }
|
||||
|
||||
// let main_fn: extern "C" fn() = std::mem::transmute(main_fn_ptr);
|
||||
// main_fn();
|
||||
// };
|
||||
// }
|
||||
|
||||
// /// Load the env file from the session cache if we're in debug mode and on android
|
||||
// ///
|
||||
// /// This is a slightly hacky way of being able to use std::env::var code in android apps without
|
||||
// /// going through their custom java-based system.
|
||||
// #[cfg(target_os = "android")]
|
||||
// fn load_env_file_from_session_cache() {
|
||||
// let env_file = dioxus_cli_config::android_session_cache_dir().join(".env");
|
||||
// if let Some(env_file) = std::fs::read_to_string(&env_file).ok() {
|
||||
// for line in env_file.lines() {
|
||||
// if let Some((key, value)) = line.trim().split_once('=') {
|
||||
// std::env::set_var(key, value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
use crate::Config;
|
||||
use crate::{
|
||||
app::App,
|
||||
@@ -8,52 +233,6 @@ use dioxus_document::eval;
|
||||
use std::any::Any;
|
||||
use tao::event::{Event, StartCause, WindowEvent};
|
||||
|
||||
/// Launches the WebView and runs the event loop
|
||||
pub fn launch(root: fn() -> Element) {
|
||||
launch_cfg(root, vec![], vec![]);
|
||||
}
|
||||
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch_cfg(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Vec<Box<dyn Any>>,
|
||||
) {
|
||||
let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
for context in contexts {
|
||||
virtual_dom.insert_any_root_context(context());
|
||||
}
|
||||
|
||||
let platform_config = *platform_config
|
||||
.into_iter()
|
||||
.find_map(|cfg| cfg.downcast::<Config>().ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
launch_virtual_dom(virtual_dom, platform_config)
|
||||
}
|
||||
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
|
||||
#[cfg(feature = "tokio_runtime")]
|
||||
{
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(tokio::task::unconstrained(async move {
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config)
|
||||
}));
|
||||
|
||||
unreachable!("The desktop launch function will never exit")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tokio_runtime"))]
|
||||
{
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config);
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch the WebView and run the event loop, with configuration and root props.
|
||||
///
|
||||
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
|
||||
@@ -157,68 +336,43 @@ pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, mut desktop_config:
|
||||
})
|
||||
}
|
||||
|
||||
/// Expose the `Java_dev_dioxus_main_WryActivity_create` function to the JNI layer.
|
||||
/// We hardcode these to have a single trampoline for host Java code to call into.
|
||||
///
|
||||
/// This saves us from having to plumb the top-level package name all the way down into
|
||||
/// this file. This is better for modularity (ie just call dioxus' main to run the app) as
|
||||
/// well as cache thrashing since this crate doesn't rely on external env vars.
|
||||
///
|
||||
/// The CLI is expecting to find `dev.dioxus.main` in the final library. If you find a need to
|
||||
/// change this, you'll need to change the CLI as well.
|
||||
#[cfg(target_os = "android")]
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub extern "C" fn start_app() {
|
||||
wry::android_binding!(dev_dioxus, main, wry);
|
||||
tao::android_binding!(
|
||||
dev_dioxus,
|
||||
main,
|
||||
WryActivity,
|
||||
wry::android_setup,
|
||||
dioxus_main_root_fn,
|
||||
tao
|
||||
);
|
||||
}
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) -> ! {
|
||||
#[cfg(feature = "tokio_runtime")]
|
||||
{
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(tokio::task::unconstrained(async move {
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config)
|
||||
}));
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[doc(hidden)]
|
||||
pub fn dioxus_main_root_fn() {
|
||||
// we're going to find the `main` symbol using dlsym directly and call it
|
||||
unsafe {
|
||||
let mut main_fn_ptr = libc::dlsym(libc::RTLD_DEFAULT, b"main\0".as_ptr() as _);
|
||||
unreachable!("The desktop launch function will never exit")
|
||||
}
|
||||
|
||||
if main_fn_ptr.is_null() {
|
||||
main_fn_ptr = libc::dlsym(libc::RTLD_DEFAULT, b"_main\0".as_ptr() as _);
|
||||
}
|
||||
|
||||
if main_fn_ptr.is_null() {
|
||||
panic!("Failed to find main symbol");
|
||||
}
|
||||
|
||||
// Set the env vars that rust code might expect, passed off to us by the android app
|
||||
// Doing this before main emulates the behavior of a regular executable
|
||||
if cfg!(target_os = "android") && cfg!(debug_assertions) {
|
||||
load_env_file_from_session_cache();
|
||||
}
|
||||
|
||||
let main_fn: extern "C" fn() = std::mem::transmute(main_fn_ptr);
|
||||
main_fn();
|
||||
};
|
||||
}
|
||||
|
||||
/// Load the env file from the session cache if we're in debug mode and on android
|
||||
///
|
||||
/// This is a slightly hacky way of being able to use std::env::var code in android apps without
|
||||
/// going through their custom java-based system.
|
||||
#[cfg(target_os = "android")]
|
||||
fn load_env_file_from_session_cache() {
|
||||
let env_file = dioxus_cli_config::android_session_cache_dir().join(".env");
|
||||
if let Some(env_file) = std::fs::read_to_string(&env_file).ok() {
|
||||
for line in env_file.lines() {
|
||||
if let Some((key, value)) = line.trim().split_once('=') {
|
||||
std::env::set_var(key, value);
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "tokio_runtime"))]
|
||||
{
|
||||
launch_virtual_dom_blocking(virtual_dom, desktop_config);
|
||||
}
|
||||
}
|
||||
|
||||
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
platform_config: Vec<Box<dyn Any>>,
|
||||
) -> ! {
|
||||
let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
for context in contexts {
|
||||
virtual_dom.insert_any_root_context(context());
|
||||
}
|
||||
|
||||
let platform_config = *platform_config
|
||||
.into_iter()
|
||||
.find_map(|cfg| cfg.downcast::<Config>().ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
launch_virtual_dom(virtual_dom, platform_config)
|
||||
}
|
||||
Reference in new issue
Block a user