Skip to content

Commit 723df93

Browse files
committed
cxx-qt-lib: use +whole_archive for std_types so that cargo-only works
When building with cargo we need to ensure that the statics aren't optimised out for registering types with Qt 5. Otherwise we cannot use numbers in QML. Closes #592
1 parent 0b17899 commit 723df93

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

crates/cxx-qt-build/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ impl CxxQtBuilder {
429429
// https://github.com/rust-lang/rust/issues/110912
430430
cc_builder_whole_archive.link_lib_modifier("-bundle");
431431
for builder in [&mut self.cc_builder, &mut cc_builder_whole_archive] {
432+
// Note, ensure our settings stay in sync across cxx-qt-build and cxx-qt-lib
432433
builder.cpp(true);
433434
// MSVC
434435
builder.flag_if_supported("/std:c++17");

crates/cxx-qt-lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ time = { version = "0.3.20", optional = true }
2626
url = { version = "2.3", optional = true }
2727

2828
[build-dependencies]
29+
cc.workspace = true
2930
cxx-build.workspace = true
3031
cxx-qt-lib-headers.workspace = true
3132
qt-build-utils.workspace = true

crates/cxx-qt-lib/build.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,28 @@ fn main() {
232232
}
233233
builder.file("src/qt_types.cpp");
234234
println!("cargo:rerun-if-changed=src/qt_types.cpp");
235+
println!("cargo:rerun-if-changed=src/assertion_utils.h");
236+
237+
// Setup compiler
238+
// qRegisterMetaType needs to be linked with +whole-archive
239+
// because they use static variables which need to be initialized before main
240+
// (regardless of whether main is in Rust or C++). Normally linkers only copy symbols referenced
241+
// from within main when static linking, which would result in discarding those static variables.
242+
// Use a separate cc::Build for the little amount of code that needs to be linked with +whole-archive
243+
// to avoid bloating the binary.
244+
let mut cc_builder_whole_archive = cc::Build::new();
245+
cc_builder_whole_archive.link_lib_modifier("+whole-archive");
246+
// Workaround for spurious compiler error in Rust 1.69. The bug has been fixed, but keeping this
247+
// workaround seems to be harmless.
248+
// https://github.com/rust-lang/rust/issues/110912
249+
cc_builder_whole_archive.link_lib_modifier("-bundle");
250+
for include_path in qtbuild.include_paths() {
251+
cc_builder_whole_archive.include(include_path);
252+
}
253+
cc_builder_whole_archive.file("src/std_types.cpp");
254+
// Still expose std_types.cpp to the builder so that CMake builds work
235255
builder.file("src/std_types.cpp");
236256
println!("cargo:rerun-if-changed=src/std_types.cpp");
237-
println!("cargo:rerun-if-changed=src/assertion_utils.h");
238257

239258
// Write this library's manually written C++ headers to files and add them to include paths
240259
let out_dir = std::env::var("OUT_DIR").unwrap();
@@ -251,11 +270,17 @@ fn main() {
251270
builder.define("CXX_QT_QML_FEATURE", None);
252271
}
253272

254-
// MSVC
255-
builder.flag_if_supported("/std:c++17");
256-
builder.flag_if_supported("/Zc:__cplusplus");
257-
builder.flag_if_supported("/permissive-");
258-
// GCC + Clang
259-
builder.flag_if_supported("-std=c++17");
273+
for builder in [&mut builder, &mut cc_builder_whole_archive] {
274+
// Note, ensure our settings stay in sync across cxx-qt-build and cxx-qt-lib
275+
builder.cpp(true);
276+
// MSVC
277+
builder.flag_if_supported("/std:c++17");
278+
builder.flag_if_supported("/Zc:__cplusplus");
279+
builder.flag_if_supported("/permissive-");
280+
// GCC + Clang
281+
builder.flag_if_supported("-std=c++17");
282+
}
283+
284+
cc_builder_whole_archive.compile("cxx-qt-lib-static-initializers");
260285
builder.compile("cxx-qt-lib");
261286
}

0 commit comments

Comments
 (0)