Skip to content

Commit a98b1b8

Browse files
CXX-Qt-build: Remove definitions from Interface
These definitions cannot be imported into CMake, as they are unknown at configure time. It is also best practice to keep definitions in a header file, as that allows us to only include them where really needed, as pointed out by this blog post: https://www.kdab.com/setting-defines-with-cmake/ This is the method that cxx-qt-lib now uses to configure its features. Closes #1165
1 parent 5229e31 commit a98b1b8

File tree

10 files changed

+55
-98
lines changed

10 files changed

+55
-98
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727

2828
- Build warnings due to unused unsafe blocks since CXX 1.0.130
2929

30+
### Removed
31+
32+
- CXX-Qt-build: Interface no longer includes compiler definitions (<https://github.com/KDAB/cxx-qt/issues/1165>)
33+
3034
## [0.7.0](https://github.com/KDAB/cxx-qt/compare/v0.6.1...v0.7.0) - 2024-10-30
3135

3236
### Added

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

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
88
use serde::{Deserialize, Serialize};
99

10-
use std::collections::{HashMap, HashSet};
10+
use std::collections::HashSet;
1111
use std::path::{Path, PathBuf};
1212

1313
/// When generating a library with cxx-qt-build, the library may need to export certain flags or headers.
1414
/// These are all specified by this Interface struct, which should be passed to the [crate::CxxQtBuilder::library] function.
1515
pub struct Interface {
16-
pub(crate) compile_definitions: HashMap<String, Option<String>>,
1716
pub(crate) initializers: Vec<PathBuf>,
1817
// The name of the links keys, whose CXX-Qt dependencies to reexport
1918
pub(crate) reexport_links: HashSet<String>,
@@ -29,7 +28,6 @@ pub struct Interface {
2928
impl Default for Interface {
3029
fn default() -> Self {
3130
Self {
32-
compile_definitions: HashMap::new(),
3331
initializers: Vec::new(),
3432
reexport_links: HashSet::new(),
3533
exported_include_prefixes: vec![super::crate_name()],
@@ -39,32 +37,6 @@ impl Default for Interface {
3937
}
4038

4139
impl Interface {
42-
/// Add a compile-time-definition for the C++ code built by this crate and all downstream
43-
/// dependencies
44-
///
45-
/// This function will panic if the variable has already been defined with a different value.
46-
///
47-
/// Also please note that any definitions added here will only be exported throughout the cargo
48-
/// build. Due to technical limitations, they can not be imported into CMake with the
49-
/// cxxqt_import_crate function.
50-
pub fn define(mut self, variable: &str, value: Option<&str>) -> Self {
51-
use std::collections::hash_map::Entry::*;
52-
53-
let entry = self.compile_definitions.entry(variable.to_owned());
54-
match entry {
55-
Vacant(entry) => entry.insert(value.map(String::from)),
56-
Occupied(entry) => {
57-
if entry.get().as_deref() == value {
58-
println!("Warning: Silently ignoring duplicate compiler definition for {variable} with {value:?}.");
59-
}
60-
panic!(
61-
"Cxx-Qt-build - Error: Interface::define - Duplicate compile-time definition for variable {variable} with value {value:?}!"
62-
);
63-
}
64-
};
65-
self
66-
}
67-
6840
/// Add a C++ file path that will be exported as an initializer to downstream dependencies.
6941
///
7042
/// Initializer files will be built into object files, instead of linked into the static
@@ -152,7 +124,6 @@ pub(crate) struct Manifest {
152124
pub(crate) name: String,
153125
pub(crate) link_name: String,
154126
pub(crate) qt_modules: Vec<String>,
155-
pub(crate) defines: Vec<(String, Option<String>)>,
156127
pub(crate) initializers: Vec<PathBuf>,
157128
pub(crate) exported_include_prefixes: Vec<String>,
158129
}
@@ -257,43 +228,3 @@ pub(crate) fn reexported_dependencies(
257228
}
258229
exported_dependencies
259230
}
260-
261-
pub(crate) fn all_compile_definitions(
262-
interface: Option<&Interface>,
263-
dependencies: &[Dependency],
264-
) -> Vec<(String, Option<String>)> {
265-
// For each definition, store the name of the crate that defines it so we can generate a
266-
// nicer error message
267-
let mut definitions: HashMap<String, (Option<String>, String)> = interface
268-
.iter()
269-
.flat_map(|interface| &interface.compile_definitions)
270-
.map(|(key, value)| (key.clone(), (value.clone(), crate::crate_name())))
271-
.collect();
272-
273-
for dependency in dependencies {
274-
for (variable, value) in &dependency.manifest.defines {
275-
use std::collections::hash_map::Entry::*;
276-
let entry = definitions.entry(variable.to_owned());
277-
278-
match entry {
279-
Vacant(entry) => {
280-
entry.insert((value.to_owned(), dependency.manifest.name.clone()));
281-
}
282-
Occupied(entry) => {
283-
let existing_value = &entry.get().0;
284-
// Only allow duplicate definitions with the same value
285-
if existing_value != value {
286-
panic!("Conflicting compiler definitions requested!\nCrate {existing} exports {variable}={existing_value:?}, and crate {conflicting} exports {variable}={value:?}",
287-
existing=entry.get().1,
288-
conflicting = dependency.manifest.name);
289-
}
290-
}
291-
}
292-
}
293-
}
294-
295-
definitions
296-
.into_iter()
297-
.map(|(key, (value, _crate_name))| (key, value))
298-
.collect()
299-
}

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

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -657,11 +657,7 @@ impl CxxQtBuilder {
657657
}
658658
}
659659

660-
fn setup_cc_builder(
661-
builder: &mut cc::Build,
662-
include_paths: &[impl AsRef<Path>],
663-
defines: &[(String, Option<String>)],
664-
) {
660+
fn setup_cc_builder(builder: &mut cc::Build, include_paths: &[impl AsRef<Path>]) {
665661
// Note, ensure our settings stay in sync across cxx-qt and cxx-qt-lib
666662
builder.cpp(true);
667663
builder.std("c++17");
@@ -672,11 +668,6 @@ impl CxxQtBuilder {
672668
// MinGW requires big-obj otherwise debug builds fail
673669
builder.flag_if_supported("-Wa,-mbig-obj");
674670

675-
// Enable any extra defines
676-
for (variable, value) in defines {
677-
builder.define(variable, value.as_deref());
678-
}
679-
680671
for include_path in include_paths {
681672
builder.include(include_path);
682673
}
@@ -967,13 +958,11 @@ impl CxxQtBuilder {
967958
let initializers = initializers.into_iter().collect();
968959
let exported_include_prefixes =
969960
dependencies::all_include_prefixes(interface, &dependencies);
970-
let defines = dependencies::all_compile_definitions(Some(interface), &dependencies);
971961

972962
let manifest = Manifest {
973963
name: crate_name(),
974964
link_name: link_name()
975965
.expect("The links key must be set when creating a library with CXX-Qt-build!"),
976-
defines,
977966
initializers,
978967
qt_modules: qt_modules.into_iter().collect(),
979968
exported_include_prefixes,
@@ -1059,11 +1048,9 @@ impl CxxQtBuilder {
10591048
// to the generated files without any namespacing.
10601049
include_paths.push(header_root.join(&self.include_prefix));
10611050

1062-
let compile_definitions =
1063-
dependencies::all_compile_definitions(self.public_interface.as_ref(), &dependencies);
1064-
Self::setup_cc_builder(&mut self.cc_builder, &include_paths, &compile_definitions);
1051+
Self::setup_cc_builder(&mut self.cc_builder, &include_paths);
10651052

1066-
Self::setup_cc_builder(&mut init_builder, &include_paths, &compile_definitions);
1053+
Self::setup_cc_builder(&mut init_builder, &include_paths);
10671054
// Note: From now on the init_builder is correctly configured.
10681055
// When building object files with this builder, we always need to copy it first.
10691056
// So remove `mut` to ensure that we can't accidentally change the configuration or add

crates/cxx-qt-lib/build.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@ fn write_headers_in(subfolder: &str) {
4343
}
4444
}
4545

46+
fn write_definitions_header() {
47+
// We cannot ensure that downstream dependencies set the same compile-time definitions.
48+
// So we generate a header file that adds those definitions, which will be passed along
49+
// to downstream dependencies with all other headers.
50+
//
51+
// Thanks to David Faure for reminding us of this useful trick in his blog post:
52+
// https://www.kdab.com/setting-defines-with-cmake/
53+
let mut definitions = "#pragma once\n".to_owned();
54+
55+
if qt_gui_enabled() {
56+
definitions.push_str("#define CXX_QT_GUI_FEATURE\n");
57+
}
58+
59+
if qt_qml_enabled() {
60+
definitions.push_str("#define CXX_QT_QML_FEATURE\n");
61+
}
62+
63+
if qt_quickcontrols_enabled() {
64+
definitions.push_str("#define CXX_QT_QUICKCONTROLS_FEATURE\n");
65+
}
66+
67+
std::fs::write(header_dir().join("definitions.h"), definitions)
68+
.expect("Failed to write cxx-qt-lib/definitions.h");
69+
}
70+
4671
fn write_headers() {
4772
println!("cargo::rerun-if-changed=include/");
4873
std::fs::create_dir_all(header_dir()).expect("Failed to create include directory");
@@ -66,6 +91,8 @@ fn write_headers() {
6691
if qt_quickcontrols_enabled() {
6792
write_headers_in("quickcontrols");
6893
}
94+
95+
write_definitions_header();
6996
}
7097

7198
fn main() {
@@ -323,17 +350,7 @@ fn main() {
323350
.reexport_dependency("cxx-qt");
324351

325352
if qt_gui_enabled() {
326-
interface = interface
327-
.define("CXX_QT_GUI_FEATURE", None)
328-
.initializer("src/gui/init.cpp");
329-
}
330-
331-
if qt_qml_enabled() {
332-
interface = interface.define("CXX_QT_QML_FEATURE", None);
333-
}
334-
335-
if qt_quickcontrols_enabled() {
336-
interface = interface.define("CXX_QT_QUICKCONTROLS_FEATURE", None);
353+
interface = interface.initializer("src/gui/init.cpp");
337354
}
338355

339356
let mut builder = CxxQtBuilder::library(interface).include_prefix("cxx-qt-lib-internals");

crates/cxx-qt-lib/include/core/qlist.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#include <cstdint>
1010

11+
// The definitions file is auto-generated by the build script
12+
#include <cxx-qt-lib/definitions.h>
13+
1114
#include <QtCore/QList>
1215

1316
#include <QtCore/QByteArray>

crates/cxx-qt-lib/include/core/qvariant.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
#include <cstdint>
1111

12+
// The definitions file is auto-generated by the build script
13+
#include <cxx-qt-lib/definitions.h>
14+
1215
#include <QtCore/QVariant>
1316

1417
#include <QtCore/QByteArray>

crates/cxx-qt-lib/include/core/qvector.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#include <cstdint>
1010

11+
// The definitions file is auto-generated by the build script
12+
#include <cxx-qt-lib/definitions.h>
13+
1114
#include <QtCore/QVector>
1215

1316
#include <QtCore/QByteArray>

crates/cxx-qt-lib/include/qml/qqmlapplicationengine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// SPDX-License-Identifier: MIT OR Apache-2.0
77
#pragma once
88

9+
// The definitions file is auto-generated by the build script
10+
#include <cxx-qt-lib/definitions.h>
11+
912
#ifdef CXX_QT_QML_FEATURE
1013

1114
#include <memory>

crates/cxx-qt-lib/include/qml/qqmlengine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// SPDX-License-Identifier: MIT OR Apache-2.0
77
#pragma once
88

9+
// The definitions file is auto-generated by the build script
10+
#include <cxx-qt-lib/definitions.h>
11+
912
#ifdef CXX_QT_QML_FEATURE
1013

1114
#include <memory>

crates/cxx-qt-lib/include/quickcontrols/qquickstyle.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// SPDX-License-Identifier: MIT OR Apache-2.0
77
#pragma once
88

9+
// The definitions file is auto-generated by the build script
10+
#include <cxx-qt-lib/definitions.h>
11+
912
#ifdef CXX_QT_QUICKCONTROLS_FEATURE
1013

1114
#include <memory>
@@ -27,4 +30,4 @@ qquickstyleSetStyle(const QString& style);
2730
}
2831
}
2932

30-
#endif
33+
#endif

0 commit comments

Comments
 (0)