diff --git a/api/sixtyfps-rs/sixtyfps-build/lib.rs b/api/sixtyfps-rs/sixtyfps-build/lib.rs index 7613bbdfac3..2d4f8525ee3 100644 --- a/api/sixtyfps-rs/sixtyfps-build/lib.rs +++ b/api/sixtyfps-rs/sixtyfps-build/lib.rs @@ -269,5 +269,25 @@ pub fn compile_with_config( println!("cargo:rerun-if-env-changed=SIXTYFPS_STYLE"); println!("cargo:rustc-env=SIXTYFPS_INCLUDE_GENERATED={}", output_file_path.display()); + + apply_linker_flags(); + Ok(()) } + +// Backends such as Qt or the MCU might need special link flags. We don't want to require users to have to +// deal with those, so propagate them here. +fn apply_linker_flags() { + // Same logic as in sixtyfps-rendering-backend-default's build script to get the path + if let Some(path) = std::env::var_os("OUT_DIR").and_then(|path| { + Some(Path::new(&path).parent()?.parent()?.join("SIXTYFPS_BACKEND_LINK_FLAGS.txt")) + }) { + // unfortunately, if for some reason the file is changed, it is changed after cargo decide to re-run + // this build script or not. So that means one will need two build to settle the right thing. + println!("cargo:rerun-if-changed={}", path.display()); + + if let Ok(mut link_flags_file) = std::fs::File::open(path) { + std::io::copy(&mut link_flags_file, &mut std::io::stdout()).ok(); + } + } +} diff --git a/sixtyfps_runtime/rendering_backends/default/build.rs b/sixtyfps_runtime/rendering_backends/default/build.rs index fc19cb9760c..f5c6c216100 100644 --- a/sixtyfps_runtime/rendering_backends/default/build.rs +++ b/sixtyfps_runtime/rendering_backends/default/build.rs @@ -1,6 +1,7 @@ // Copyright © SixtyFPS GmbH // SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial) +use std::fmt::Write; use std::path::Path; fn main() { @@ -28,8 +29,38 @@ fn main() { // out_dir is something like // /build/sixtyfps-rendering-backend-default-1fe5c4ab61eb0584/out // and we want to write to a common directory, so write in the build/ dir - let target_path = + let style_target_path = Path::new(&out_dir).parent().unwrap().parent().unwrap().join("SIXTYFPS_DEFAULT_STYLE.txt"); - std::fs::write(target_path, if has_native_style { b"native\n" as &[u8] } else { b"fluent\n" }) - .unwrap(); + std::fs::write( + style_target_path, + if has_native_style { b"native\n" as &[u8] } else { b"fluent\n" }, + ) + .unwrap(); + + let mut link_flags = String::new(); + + for backend in ["GL", "QT"] { + if let Ok(args) = + std::env::var(format!("DEP_SIXTYFPS_RENDERING_BACKEND_{}_LINK_ARGS", backend)) + { + for arg in args.split('|') { + write!(&mut link_flags, "cargo:rustc-link-arg={}\n", arg).unwrap(); + } + } + if let Ok(args) = + std::env::var(format!("DEP_SIXTYFPS_RENDERING_BACKEND_{}_LINK_SEARCH_PATHS", backend)) + { + for arg in args.split('|') { + write!(&mut link_flags, "cargo:rustc-link-search={}\n", arg).unwrap(); + } + } + } + + let link_flags_target_path = std::path::Path::new(&out_dir) + .parent() + .unwrap() + .parent() + .unwrap() + .join("SIXTYFPS_BACKEND_LINK_FLAGS.txt"); + std::fs::write(link_flags_target_path, link_flags).unwrap(); } diff --git a/sixtyfps_runtime/rendering_backends/qt/build.rs b/sixtyfps_runtime/rendering_backends/qt/build.rs index c89f786618c..b0ac6476eac 100644 --- a/sixtyfps_runtime/rendering_backends/qt/build.rs +++ b/sixtyfps_runtime/rendering_backends/qt/build.rs @@ -38,9 +38,11 @@ fn main() { // Ref: https://docs.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8 config.flag_if_supported("/utf-8"); + let qt_library_path = std::env::var("DEP_QT_LIBRARY_PATH").unwrap(); + if cfg!(target_os = "macos") { config.flag("-F"); - config.flag(&std::env::var("DEP_QT_LIBRARY_PATH").unwrap()); + config.flag(&qt_library_path); } config.include(std::env::var("DEP_QT_INCLUDE_PATH").unwrap()).build("lib.rs"); @@ -58,4 +60,14 @@ fn main() { println!("cargo:rerun-if-changed=qt_widgets/tabwidget.rs"); println!("cargo:rerun-if-changed=lib.rs"); println!("cargo:SUPPORTS_NATIVE_STYLE=1"); + + // Cargo doesn't support implicit transitive link flags for crates (https://github.com/rust-lang/cargo/issues/9554 | https://github.com/rust-lang/cargo/issues/9562 | https://github.com/sixtyfpsui/sixtyfps/issues/566). + // Instead of requiring Rust apps to have Qt backend specific code, propagate the needed rpath link options via a DEP_ variable to the default backend, which + // can write it to a file for use by sixtyfps-build. + // For C++ apps that's not an issue because we create a cdylib, qttypes emits `rustc-cdylib-link-arg` and that *is* propagated. + // This also means that the Qt backend cannot be combined with another backend that also writes to this file. The GL backend doesn't, but the MCU + // backend might/will. + if std::env::var("CARGO_CFG_TARGET_FAMILY").as_ref().map(|s| s.as_ref()) == Ok("unix") { + println!("cargo:LINK_ARGS=-Wl,-rpath,{}", &qt_library_path) + } }