Skip to content

Commit 4678642

Browse files
committed
Set the rpath to Qt for Rust binaries
For C++ apps we apply rpath to the cdylib implicitly via qttypes, but link flags for rust binaries are not transitively propagated but require explicit opt-in by the top-level crate. However we want that convenience, to avoid Rust apps having to deal with Qt backend specific code in their build.rs. Therefore we use the _DEP mechanism to get the qt library path from the qttypes crate and write it into a generic file in the qt backend's build.rs, which is then picked up by sixtyfps-build. We'll use the same mechanism to propagate link flags for the MCU build (such as the linker script). cc #566
1 parent 2401eea commit 4678642

File tree

2 files changed

+47
-1
lines changed
  • api/sixtyfps-rs/sixtyfps-build
  • sixtyfps_runtime/rendering_backends/qt

2 files changed

+47
-1
lines changed

api/sixtyfps-rs/sixtyfps-build/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,5 +269,25 @@ pub fn compile_with_config(
269269
println!("cargo:rerun-if-env-changed=SIXTYFPS_STYLE");
270270

271271
println!("cargo:rustc-env=SIXTYFPS_INCLUDE_GENERATED={}", output_file_path.display());
272+
273+
apply_linker_flags();
274+
272275
Ok(())
273276
}
277+
278+
// Backends such as Qt or the MCU might need special link flags. We don't want to require users to have to
279+
// deal with those, so propagate them here.
280+
fn apply_linker_flags() {
281+
// Same logic as in sixtyfps-rendering-backend-qt's build script to get the path
282+
if let Some(path) = std::env::var_os("OUT_DIR").and_then(|path| {
283+
Some(Path::new(&path).parent()?.parent()?.join("SIXTYFPS_BACKEND_LINK_FLAGS.txt"))
284+
}) {
285+
// unfortunately, if for some reason the file is changed, it is changed after cargo decide to re-run
286+
// this build script or not. So that means one will need two build to settle the right thing.
287+
println!("cargo:rerun-if-changed={}", path.display());
288+
289+
if let Ok(mut link_flags_file) = std::fs::File::open(path) {
290+
std::io::copy(&mut link_flags_file, &mut std::io::stdout()).ok();
291+
}
292+
}
293+
}

sixtyfps_runtime/rendering_backends/qt/build.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ fn main() {
3838
// Ref: https://docs.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8
3939
config.flag_if_supported("/utf-8");
4040

41+
let qt_library_path = std::env::var("DEP_QT_LIBRARY_PATH").unwrap();
42+
4143
if cfg!(target_os = "macos") {
4244
config.flag("-F");
43-
config.flag(&std::env::var("DEP_QT_LIBRARY_PATH").unwrap());
45+
config.flag(&qt_library_path);
4446
}
4547
config.include(std::env::var("DEP_QT_INCLUDE_PATH").unwrap()).build("lib.rs");
4648

@@ -58,4 +60,28 @@ fn main() {
5860
println!("cargo:rerun-if-changed=qt_widgets/tabwidget.rs");
5961
println!("cargo:rerun-if-changed=lib.rs");
6062
println!("cargo:SUPPORTS_NATIVE_STYLE=1");
63+
64+
// 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).
65+
// Instead of requiring Rust apps to have Qt backend specific code, write the needed rpath link options into a file that sixtyfps-build can find later.
66+
// For C++ apps that's not an issue because we create a cdylib, qttypes emits `rustc-cdylib-link-arg` and that *is* propagated.
67+
// 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
68+
// backend might/will.
69+
let link_flags =
70+
if std::env::var("CARGO_CFG_TARGET_FAMILY").as_ref().map(|s| s.as_ref()) == Ok("unix") {
71+
format!("cargo:rustc-link-arg=-Wl,-rpath,{}", &qt_library_path)
72+
} else {
73+
String::new()
74+
};
75+
76+
let out_dir = std::env::var_os("OUT_DIR").unwrap();
77+
// out_dir is something like
78+
// <target_dir>/build/sixtyfps-rendering-backend-qt-1fe5c4ab61eb0584/out
79+
// and we want to write to a common directory, so write in the build/ dir
80+
let target_path = std::path::Path::new(&out_dir)
81+
.parent()
82+
.unwrap()
83+
.parent()
84+
.unwrap()
85+
.join("SIXTYFPS_BACKEND_LINK_FLAGS.txt");
86+
std::fs::write(target_path, link_flags).unwrap();
6187
}

0 commit comments

Comments
 (0)