Skip to content

Commit c8ef171

Browse files
committed
qt-build-utils: add a helper for generating cfg
1 parent 0fba618 commit c8ef171

File tree

4 files changed

+137
-68
lines changed

4 files changed

+137
-68
lines changed

crates/cxx-qt-build/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ qt-build-utils = { workspace = true, features = ["serde"] }
2323
codespan-reporting = "0.11"
2424
serde.workspace = true
2525
serde_json = "1.0"
26-
semver.workspace = true
2726

2827
[features]
2928
link_qt_object_files = ["qt-build-utils/link_qt_object_files"]

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

Lines changed: 8 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ pub use qml_modules::QmlModule;
3636

3737
pub use qt_build_utils::MocArguments;
3838
use quote::ToTokens;
39-
use semver::Version;
4039
use std::{
4140
collections::HashSet,
4241
env,
@@ -608,71 +607,6 @@ impl CxxQtBuilder {
608607
self
609608
}
610609

611-
fn define_cfg_variable(key: String, value: Option<&str>) {
612-
if let Some(value) = value {
613-
println!("cargo::rustc-cfg={key}=\"{value}\"");
614-
} else {
615-
println!("cargo::rustc-cfg={key}");
616-
}
617-
let variable_cargo = format!("CARGO_CFG_{key}");
618-
env::set_var(variable_cargo, value.unwrap_or("true"));
619-
}
620-
621-
fn define_cfg_check_variable(key: String, values: Option<Vec<&str>>) {
622-
if let Some(values) = values {
623-
let values = values
624-
.iter()
625-
// Escape and add quotes
626-
.map(|value| format!("\"{}\"", value.escape_default()))
627-
.collect::<Vec<_>>()
628-
.join(", ");
629-
println!("cargo::rustc-check-cfg=cfg({key}, values({values}))");
630-
} else {
631-
println!("cargo::rustc-check-cfg=cfg({key})");
632-
}
633-
}
634-
635-
fn define_qt_version_cfg_variables(version: Version) {
636-
// Allow for Qt 5 or Qt 6 as valid values
637-
CxxQtBuilder::define_cfg_check_variable(
638-
"cxxqt_qt_version_major".to_owned(),
639-
Some(vec!["5", "6"]),
640-
);
641-
// Find the Qt version and tell the Rust compiler
642-
// this allows us to have conditional Rust code
643-
CxxQtBuilder::define_cfg_variable(
644-
"cxxqt_qt_version_major".to_owned(),
645-
Some(version.major.to_string().as_str()),
646-
);
647-
648-
// Seed all values from Qt 5.0 through to Qt 7.99
649-
for major in 5..=7 {
650-
CxxQtBuilder::define_cfg_check_variable(
651-
format!("cxxqt_qt_version_at_least_{major}"),
652-
None,
653-
);
654-
655-
for minor in 0..=99 {
656-
CxxQtBuilder::define_cfg_check_variable(
657-
format!("cxxqt_qt_version_at_least_{major}_{minor}"),
658-
None,
659-
);
660-
}
661-
}
662-
663-
for minor in 0..=version.minor {
664-
let qt_version_at_least =
665-
format!("cxxqt_qt_version_at_least_{}_{}", version.major, minor);
666-
CxxQtBuilder::define_cfg_variable(qt_version_at_least, None);
667-
}
668-
669-
// We don't support Qt < 5
670-
for major in 5..=version.major {
671-
let at_least_qt_major_version = format!("cxxqt_qt_version_at_least_{major}");
672-
CxxQtBuilder::define_cfg_variable(at_least_qt_major_version, None);
673-
}
674-
}
675-
676610
fn write_common_headers() {
677611
let header_root = dir::header_root();
678612
// Write cxx headers
@@ -1103,7 +1037,14 @@ extern "C" bool {init_fun}() {{
11031037
let mut qtbuild = qt_build_utils::QtBuild::new(qt_modules.iter().cloned().collect())
11041038
.expect("Could not find Qt installation");
11051039
qtbuild.cargo_link_libraries(&mut self.cc_builder);
1106-
Self::define_qt_version_cfg_variables(qtbuild.version());
1040+
1041+
// Define the Qt cfg to cargo
1042+
//
1043+
// TODO: do we have this as a helper on QtBuild too?
1044+
qt_build_utils::CfgGenerator::new(qtbuild.version())
1045+
.prefix("cxxqt_".to_string())
1046+
.range_major(5..=7)
1047+
.build();
11071048

11081049
// Ensure that Qt modules and apple framework are linked and searched correctly
11091050
let mut include_paths = qtbuild.include_paths();

crates/qt-build-utils/src/cfg.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
2+
// SPDX-FileContributor: Andrew Hayzen <[email protected]>
3+
//
4+
// SPDX-License-Identifier: MIT OR Apache-2.0
5+
6+
use semver::Version;
7+
use std::ops::RangeInclusive;
8+
9+
/// Helper for generating cargo cfg for a version range
10+
pub struct CfgGenerator {
11+
prefix: Option<String>,
12+
range_major: RangeInclusive<u64>,
13+
range_minor: RangeInclusive<u64>,
14+
version: Version,
15+
}
16+
17+
impl CfgGenerator {
18+
/// Construct a new [CfgGenerator]
19+
pub fn new(version: Version) -> Self {
20+
Self {
21+
range_major: (0..=99),
22+
range_minor: (0..=99),
23+
prefix: None,
24+
version,
25+
}
26+
}
27+
28+
/// Specify a prefix for the [CfgGenerator]
29+
pub fn prefix(mut self, prefix: String) -> Self {
30+
self.prefix = Some(prefix);
31+
self
32+
}
33+
34+
/// Specify a major range for the [CfgGenerator]
35+
pub fn range_major(mut self, range: RangeInclusive<u64>) -> Self {
36+
self.range_major = range;
37+
self
38+
}
39+
40+
/// Specify a minor range for the [CfgGenerator]
41+
pub fn range_minor(mut self, range: RangeInclusive<u64>) -> Self {
42+
self.range_minor = range;
43+
self
44+
}
45+
46+
/// Generate cargo cfg with any given prefix and ranges for the version
47+
pub fn build(self) {
48+
// Define the major version
49+
self.define_cfg_check_variable(
50+
"qt_version_major".to_string(),
51+
Some(
52+
self.range_major
53+
.clone()
54+
.map(|major| major.to_string())
55+
.collect(),
56+
),
57+
);
58+
self.define_cfg_variable(
59+
"qt_version_major".to_string(),
60+
Some(self.version.major.to_string()),
61+
);
62+
63+
// Tell cargo about all the possible cfg variables
64+
for major in self.range_major.clone() {
65+
self.define_cfg_check_variable(format!("qt_version_at_least_{major}"), None);
66+
67+
for minor in self.range_minor.clone() {
68+
self.define_cfg_check_variable(
69+
format!("qt_version_at_least_{major}_{minor}"),
70+
None,
71+
);
72+
}
73+
}
74+
75+
// Tell cargo which major versions have been reached
76+
for major in *self.range_major.start()..=self.version.major {
77+
self.define_cfg_variable(format!("qt_version_at_least_{major}"), None);
78+
}
79+
80+
// Tell cargo which minor versions with the major have been reached
81+
for minor in *self.range_minor.start()..=self.version.minor {
82+
let major = self.version.major;
83+
self.define_cfg_variable(format!("qt_version_at_least_{major}_{minor}"), None);
84+
}
85+
}
86+
}
87+
88+
impl CfgGenerator {
89+
fn define_cfg_check_variable(&self, key: String, values: Option<Vec<String>>) {
90+
let key = self.key_with_prefix(key);
91+
92+
if let Some(values) = values {
93+
let values = values
94+
.iter()
95+
// Escape and add quotes
96+
.map(|value| format!("\"{}\"", value.escape_default()))
97+
.collect::<Vec<_>>()
98+
.join(", ");
99+
100+
println!("cargo::rustc-check-cfg=cfg({key}, values({values}))");
101+
} else {
102+
println!("cargo::rustc-check-cfg=cfg({key})");
103+
}
104+
}
105+
106+
fn define_cfg_variable(&self, key: String, value: Option<String>) {
107+
let key = self.key_with_prefix(key);
108+
109+
if let Some(value) = &value {
110+
println!("cargo::rustc-cfg={key}=\"{}\"", value.escape_default());
111+
} else {
112+
println!("cargo::rustc-cfg={key}");
113+
}
114+
115+
let variable_cargo = format!("CARGO_CFG_{key}");
116+
std::env::set_var(variable_cargo, value.unwrap_or("true".to_string()));
117+
}
118+
119+
fn key_with_prefix(&self, key: String) -> String {
120+
if let Some(prefix) = &self.prefix {
121+
format!("{prefix}{key}")
122+
} else {
123+
key
124+
}
125+
}
126+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
1616
#![allow(clippy::too_many_arguments)]
1717

18+
mod cfg;
19+
pub use cfg::CfgGenerator;
20+
1821
mod error;
1922
pub use error::QtBuildError;
2023

0 commit comments

Comments
 (0)