diff --git a/src/builders/build_monado.rs b/src/builders/build_monado.rs index a095076..b0ba80a 100644 --- a/src/builders/build_monado.rs +++ b/src/builders/build_monado.rs @@ -9,7 +9,11 @@ use std::{ path::Path, }; -pub fn get_build_monado_jobs(profile: &Profile, clean_build: bool) -> VecDeque { +pub fn get_build_monado_jobs( + profile: &Profile, + clean_build: bool, + debug_build: bool, +) -> VecDeque { let mut jobs = VecDeque::::new(); let git = Git { @@ -39,17 +43,36 @@ pub fn get_build_monado_jobs(profile: &Profile, clean_build: bool) -> VecDeque = HashMap::new(); - cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "Release".into()); + cmake_vars.insert( + "CMAKE_BUILD_TYPE".into(), + (if debug_build { "Debug" } else { "Release" }).into(), + ); cmake_vars.insert("XRT_HAVE_SYSTEM_CJSON".into(), "NO".into()); cmake_vars.insert("CMAKE_LIBDIR".into(), format!("{}/lib", profile.prefix)); cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone()); cmake_vars.insert( "CMAKE_C_FLAGS".into(), - format!("-Wl,-rpath='{}/lib'", profile.prefix), + format!( + "-Wl,-rpath='{}/lib'{}", + profile.prefix, + if debug_build { + " -g -march=native -O3 -fno-omit-frame-pointer" + } else { + "" + } + ), ); cmake_vars.insert( "CMAKE_CXX_FLAGS".into(), - format!("-Wl,-rpath='{}/lib'", profile.prefix), + format!( + "-Wl,-rpath='{}/lib'{}", + profile.prefix, + if debug_build { + " -g -march=native -O3 -fno-omit-frame-pointer" + } else { + "" + } + ), ); profile.xrservice_cmake_flags.iter().for_each(|(k, v)| { if k == "CMAKE_C_FLAGS" || k == "CMAKE_CXX_FLAGS" { diff --git a/src/builders/build_wivrn.rs b/src/builders/build_wivrn.rs index 8fbbc44..f974d8f 100644 --- a/src/builders/build_wivrn.rs +++ b/src/builders/build_wivrn.rs @@ -9,7 +9,11 @@ use std::{ path::Path, }; -pub fn get_build_wivrn_jobs(profile: &Profile, clean_build: bool) -> VecDeque { +pub fn get_build_wivrn_jobs( + profile: &Profile, + clean_build: bool, + debug_build: bool, +) -> VecDeque { let mut jobs = VecDeque::::new(); let git = Git { @@ -35,17 +39,33 @@ pub fn get_build_wivrn_jobs(profile: &Profile, clean_build: bool) -> VecDeque = HashMap::new(); - cmake_vars.insert("CMAKE_BUILD_TYPE".into(), "Release".into()); + cmake_vars.insert( + "CMAKE_BUILD_TYPE".into(), + (if debug_build { "Debug" } else { "Release" }).into(), + ); cmake_vars.insert("XRT_HAVE_SYSTEM_CJSON".into(), "NO".into()); cmake_vars.insert("WIVRN_BUILD_CLIENT".into(), "OFF".into()); cmake_vars.insert("CMAKE_INSTALL_PREFIX".into(), profile.prefix.clone()); - profile.xrservice_cmake_flags.iter().for_each(|(k, v)| { - if k == "CMAKE_C_FLAGS" || k == "CMAKE_CXX_FLAGS" { - cmake_vars.insert(k.clone(), format!("{} {}", cmake_vars.get(k).unwrap(), v)); - } else { - cmake_vars.insert(k.clone(), v.clone()); + + if debug_build { + for k in ["CMAKE_C_FLAGS", "CMAKE_CXX_FLAGS"] { + cmake_vars.insert( + k.into(), + "-g -march=native -O3 -fno-omit-frame-pointer".into(), + ); } - }); + profile.xrservice_cmake_flags.iter().for_each(|(k, v)| { + if k == "CMAKE_C_FLAGS" || k == "CMAKE_CXX_FLAGS" { + cmake_vars.insert(k.clone(), format!("{} {}", cmake_vars.get(k).unwrap(), v)); + } else { + cmake_vars.insert(k.clone(), v.clone()); + } + }); + } else { + profile.xrservice_cmake_flags.iter().for_each(|(k, v)| { + cmake_vars.insert(k.clone(), v.clone()); + }); + } let cmake = Cmake { env: None, diff --git a/src/ui/app.rs b/src/ui/app.rs index 2cf863a..976118d 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -108,10 +108,11 @@ pub enum Msg { OnBuildLog(Vec), OnBuildExit(i32), ClockTicking, - BuildProfile(bool), + BuildProfile(bool, bool), CancelBuild, EnableDebugViewChanged(bool), DoStartStopXRService, + StartWithDebug, RestartXRService, ProfileSelected(Profile), DeleteProfile, @@ -148,7 +149,7 @@ impl App { } } - pub fn start_xrservice(&mut self, sender: ComponentSender) { + pub fn start_xrservice(&mut self, sender: ComponentSender, debug: bool) { let prof = self.get_selected_profile(); if set_current_active_runtime_to_profile(&prof).is_err() { alert( @@ -179,6 +180,7 @@ impl App { JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows), JobWorkerOut::Exit(code) => Msg::OnServiceExit(code), }, + debug ); worker.start(); self.xrservice_worker = Some(worker); @@ -324,7 +326,7 @@ impl SimpleComponent for App { self.xrservice_worker = None; if self.restart_xrservice { self.restart_xrservice = false; - self.start_xrservice(sender); + self.start_xrservice(sender, false); } } Msg::ClockTicking => { @@ -388,21 +390,24 @@ impl SimpleComponent for App { } Msg::DoStartStopXRService => match &mut self.xrservice_worker { None => { - self.start_xrservice(sender); + self.start_xrservice(sender, false); } Some(_) => { self.shutdown_xrservice(); } }, + Msg::StartWithDebug => { + self.start_xrservice(sender, true) + } Msg::RestartXRService => match &mut self.xrservice_worker { None => { - self.start_xrservice(sender); + self.start_xrservice(sender, false); } Some(worker) => { let status = worker.state.lock().unwrap().exit_status.clone(); match status { Some(_) => { - self.start_xrservice(sender); + self.start_xrservice(sender, false); } None => { self.shutdown_xrservice(); @@ -411,7 +416,7 @@ impl SimpleComponent for App { } } }, - Msg::BuildProfile(clean_build) => { + Msg::BuildProfile(clean_build, debug_build) => { let profile = self.get_selected_profile(); let mut missing_deps = vec![]; let mut jobs = VecDeque::::new(); @@ -438,8 +443,8 @@ impl SimpleComponent for App { jobs.push_back(get_build_mercury_job(&profile)); } jobs.extend(match profile.xrservice_type { - XRServiceType::Monado => get_build_monado_jobs(&profile, clean_build), - XRServiceType::Wivrn => get_build_wivrn_jobs(&profile, clean_build), + XRServiceType::Monado => get_build_monado_jobs(&profile, clean_build, debug_build), + XRServiceType::Wivrn => get_build_wivrn_jobs(&profile, clean_build, debug_build), }); // no listed deps for opencomp } @@ -650,6 +655,7 @@ impl SimpleComponent for App { .forward(sender.input_sender(), |message| match message { MainViewOutMsg::EnableDebugViewChanged(val) => Msg::EnableDebugViewChanged(val), MainViewOutMsg::DoStartStopXRService => Msg::DoStartStopXRService, + MainViewOutMsg::StartWithDebug => Msg::StartWithDebug, MainViewOutMsg::RestartXRService => Msg::RestartXRService, MainViewOutMsg::ProfileSelected(uuid) => Msg::ProfileSelected(uuid), MainViewOutMsg::DeleteProfile => Msg::DeleteProfile, @@ -696,13 +702,25 @@ impl SimpleComponent for App { { withclones![sender]; stateless_action!(actions, BuildProfileAction, { - sender.input_sender().emit(Msg::BuildProfile(false)); + sender.input_sender().emit(Msg::BuildProfile(false, false)); }); } { withclones![sender]; stateless_action!(actions, BuildProfileCleanAction, { - sender.input_sender().emit(Msg::BuildProfile(true)); + sender.input_sender().emit(Msg::BuildProfile(true, false)); + }); + } + { + withclones![sender]; + stateless_action!(actions, BuildProfileDebugAction, { + sender.input_sender().emit(Msg::BuildProfile(false, true)); + }); + } + { + withclones![sender]; + stateless_action!(actions, BuildProfileCleanDebugAction, { + sender.input_sender().emit(Msg::BuildProfile(true, true)); }); } { @@ -767,6 +785,8 @@ new_action_group!(pub AppActionGroup, "win"); new_stateless_action!(pub AboutAction, AppActionGroup, "about"); new_stateless_action!(pub BuildProfileAction, AppActionGroup, "buildprofile"); new_stateless_action!(pub BuildProfileCleanAction, AppActionGroup, "buildprofileclean"); +new_stateless_action!(pub BuildProfileDebugAction, AppActionGroup, "buildprofiledebug"); +new_stateless_action!(pub BuildProfileCleanDebugAction, AppActionGroup, "buildprofilecleandebug"); new_stateless_action!(pub ConfigFbtAction, AppActionGroup, "configfbt"); new_stateless_action!(pub QuitAction, AppActionGroup, "quit"); new_stateful_action!(pub DebugViewToggleAction, AppActionGroup, "debugviewtoggle", (), bool); diff --git a/src/ui/job_worker/internal_worker.rs b/src/ui/job_worker/internal_worker.rs index c7db14d..4dfc054 100644 --- a/src/ui/job_worker/internal_worker.rs +++ b/src/ui/job_worker/internal_worker.rs @@ -157,6 +157,7 @@ impl InternalJobWorker { pub fn xrservice_worker_from_profile( prof: &Profile, state: Arc>, + debug: bool, ) -> relm4::WorkerHandle { let mut env = prof.environment.clone(); if !env.contains_key("LH_DRIVER") { @@ -165,7 +166,18 @@ impl InternalJobWorker { prof.lighthouse_driver.to_string().to_lowercase(), ); } - let launch_opts = prof.xrservice_launch_options.trim(); + let mut launch_opts = prof.xrservice_launch_options.trim(); + let debug_launch_opts = if debug { + if launch_opts.contains(LAUNCH_OPTS_CMD_PLACEHOLDER) { + format!("{} {}", "gdb -batch -ex run -ex bt --args", launch_opts) + } else { + format!( + "{} {} {}", + "gdb -batch -ex run -ex bt --args", LAUNCH_OPTS_CMD_PLACEHOLDER, launch_opts + ) + } + } else {String::default()}; + launch_opts = if debug { debug_launch_opts.as_str() } else { launch_opts }; let (command, args) = match launch_opts.is_empty() { false => ( "sh".into(), diff --git a/src/ui/job_worker/mod.rs b/src/ui/job_worker/mod.rs index 7ff802c..5d0e33e 100644 --- a/src/ui/job_worker/mod.rs +++ b/src/ui/job_worker/mod.rs @@ -48,10 +48,11 @@ impl JobWorker { prof: &Profile, sender: &Sender, transform: F, + debug: bool ) -> Self { let state = Arc::new(Mutex::new(JobWorkerState::default())); Self { - worker: InternalJobWorker::xrservice_worker_from_profile(prof, state.clone()) + worker: InternalJobWorker::xrservice_worker_from_profile(prof, state.clone(), debug) .forward(sender, transform), state, } diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index 7da9989..b1f140f 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -13,8 +13,8 @@ use crate::gpu_profile::{ use crate::profile::{LighthouseDriver, Profile}; use crate::steamvr_utils::chaperone_info_exists; use crate::ui::app::{ - AboutAction, BuildProfileAction, BuildProfileCleanAction, ConfigFbtAction, - DebugViewToggleAction, + AboutAction, BuildProfileAction, BuildProfileCleanAction, BuildProfileCleanDebugAction, + BuildProfileDebugAction, ConfigFbtAction, DebugViewToggleAction, }; use crate::ui::profile_editor::ProfileEditorInit; use crate::ui::util::{limit_dropdown_width, warning_heading}; @@ -54,6 +54,7 @@ pub struct MainView { pub enum MainViewMsg { ClockTicking, StartStopClicked, + StartWithDebug, RestartXRService, XRServiceActiveChanged(bool, Option), EnableDebugViewChanged(bool), @@ -73,6 +74,7 @@ pub enum MainViewMsg { pub enum MainViewOutMsg { EnableDebugViewChanged(bool), DoStartStopXRService, + StartWithDebug, RestartXRService, ProfileSelected(Profile), DeleteProfile, @@ -116,6 +118,10 @@ impl SimpleComponent for MainView { "C_lean Build Profile" => BuildProfileCleanAction, "Configure Full Body _Tracking" => ConfigFbtAction, }, + section! { + "Build Profile with Debug Symbols" => BuildProfileDebugAction, + "Clean Build Profile with Debug Symbols" => BuildProfileCleanDebugAction, + }, section! { "_About" => AboutAction, } @@ -155,14 +161,13 @@ impl SimpleComponent for MainView { set_margin_all: 12, set_orientation: gtk::Orientation::Vertical, gtk::Box { - set_halign: gtk::Align::Center, + set_hexpand: true, set_orientation: gtk::Orientation::Horizontal, - set_spacing: 12, + add_css_class: "linked", gtk::Button { - add_css_class: "pill", add_css_class: "suggested-action", add_css_class: "destructive-action", - set_halign: gtk::Align::Center, + set_hexpand: true, #[track = "model.changed(Self::xrservice_active())"] set_class_active: ("suggested-action", !model.xrservice_active), #[track = "model.changed(Self::xrservice_active())"] @@ -175,8 +180,14 @@ impl SimpleComponent for MainView { }, }, gtk::Button { - add_css_class: "circular", - add_css_class: "flat", + set_label: "Start with GDB", + #[track = "model.changed(Self::xrservice_active()) || model.changed(Self::enable_debug_view())"] + set_visible: model.enable_debug_view && !model.xrservice_active, + connect_clicked[sender] => move |_| { + sender.input(MainViewMsg::StartWithDebug); + }, + }, + gtk::Button { set_halign: gtk::Align::Center, set_valign: gtk::Align::Center, set_icon_name: "view-refresh-symbolic", @@ -445,6 +456,11 @@ impl SimpleComponent for MainView { .output(Self::Output::DoStartStopXRService) .expect("Sender output failed"); } + Self::Input::StartWithDebug => { + sender + .output(Self::Output::StartWithDebug) + .expect("Sender output failed"); + } Self::Input::RestartXRService => { sender .output(Self::Output::RestartXRService)