Skip to content

Commit

Permalink
C++: Add a mechanism to #define features that are enabled (#3103)
Browse files Browse the repository at this point in the history
  • Loading branch information
ogoffart committed Jul 18, 2023
1 parent 0b867f4 commit a1bf773
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 24 deletions.
4 changes: 0 additions & 4 deletions api/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,6 @@ if((SLINT_FEATURE_RENDERER_WINIT_SKIA OR SLINT_FEATURE_RENDERER_WINIT_SKIA_OPENG
endif()
endif()

if(SLINT_FEATURE_EXPERIMENTAL)
target_compile_definitions(Slint INTERFACE SLINT_FEATURE_EXPERIMENTAL)
endif()

file(GLOB api_headers RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include/"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")

Expand Down
10 changes: 8 additions & 2 deletions api/cpp/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial

use crate::cbindgen::EnabledFeatures;
use std::path::Path;
mod cbindgen;

Expand All @@ -20,8 +21,13 @@ fn main() -> Result<(), anyhow::Error> {

println!("cargo:GENERATED_INCLUDE_DIR={}", output_dir.display());

let include_interpreter = std::env::var("CARGO_FEATURE_SLINT_INTERPRETER").is_ok();
let dependencies = cbindgen::gen_all(&root_dir, &output_dir, include_interpreter)?;
let enabled_features = EnabledFeatures {
interpreter: std::env::var("CARGO_FEATURE_SLINT_INTERPRETER").is_ok(),
experimental: std::env::var("CARGO_FEATURE_SLINT_INTERPRETER").is_ok(),
backend_qt: std::env::var("CARGO_FEATURE_BACKEND_QT").is_ok(),
};

let dependencies = cbindgen::gen_all(&root_dir, &output_dir, enabled_features)?;
for path in dependencies {
println!("cargo:rerun-if-changed={}", path.display());
}
Expand Down
34 changes: 31 additions & 3 deletions api/cpp/cbindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ fn gen_corelib(
root_dir: &Path,
include_dir: &Path,
dependencies: &mut Vec<PathBuf>,
enabled_features: EnabledFeatures,
) -> anyhow::Result<()> {
let mut config = default_config();

Expand Down Expand Up @@ -448,10 +449,13 @@ fn gen_corelib(
/// This macro expands to the string representation of the version of Slint you're developing against.
/// For example if you're using version 1.5.2, this macro will expand to "1.5.2".
#define SLINT_VERSION_STRING "{x}.{y}.{z}"
{features}
"#,
x = env!("CARGO_PKG_VERSION_MAJOR"),
y = env!("CARGO_PKG_VERSION_MINOR"),
z = env!("CARGO_PKG_VERSION_PATCH"),
features = enabled_features.defines()
))
.generate()
.context("Unable to generate bindings for slint_generated_public.h")?
Expand Down Expand Up @@ -688,6 +692,30 @@ fn gen_interpreter(
Ok(())
}

#[derive(Clone, Copy)]
pub struct EnabledFeatures {
pub interpreter: bool,
pub experimental: bool,
pub backend_qt: bool,
}

impl EnabledFeatures {
/// Generate the `#define`
fn defines(self) -> String {
let mut defines = String::new();
if self.interpreter {
defines += "#define SLINT_FEATURE_INTERPRETER\n";
}
if self.experimental {
defines += "#define SLINT_FEATURE_EXPERIMENTAL\n";
}
if self.backend_qt {
defines += "#define SLINT_FEATURE_BACKEND_QT\n";
}
defines
}
}

/// Generate the headers.
/// `root_dir` is the root directory of the slint git repo
/// `include_dir` is the output directory
Expand All @@ -696,16 +724,16 @@ fn gen_interpreter(
pub fn gen_all(
root_dir: &Path,
include_dir: &Path,
include_interpreter: bool,
enabled_features: EnabledFeatures,
) -> anyhow::Result<Vec<PathBuf>> {
proc_macro2::fallback::force(); // avoid a abort if panic=abort is set
std::fs::create_dir_all(include_dir).context("Could not create the include directory")?;
let mut deps = Vec::new();
enums(&include_dir.join("slint_enums_internal.h"))?;
gen_corelib(root_dir, include_dir, &mut deps)?;
gen_corelib(root_dir, include_dir, &mut deps, enabled_features)?;
gen_backend_qt(root_dir, include_dir, &mut deps)?;
gen_backend(root_dir, include_dir, &mut deps)?;
if include_interpreter {
if enabled_features.interpreter {
gen_interpreter(root_dir, include_dir, &mut deps)?;
}
Ok(deps)
Expand Down
26 changes: 14 additions & 12 deletions api/cpp/include/slint_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

#include "slint.h"

#include "slint_interpreter_internal.h"
#ifndef SLINT_FEATURE_INTERPRETER
# warning "slint_interpreter.h API only available when SLINT_FEATURE_INTERPRETER is activated"
#else

#include <optional>
# include "slint_interpreter_internal.h"

#if !defined(DOXYGEN)
# define SLINT_QT_INTEGRATION // In the future, should be defined by cmake only if this is
// enabled
#endif
#ifdef SLINT_QT_INTEGRATION
# include <optional>

# ifdef SLINT_FEATURE_BACKEND_QT
class QWidget;
#endif
# endif

namespace slint::cbindgen_private {
// This has to stay opaque, but VRc don't compile if it is just forward declared
Expand Down Expand Up @@ -96,7 +96,7 @@ struct Struct
/// advanced until it equals \a end.
template<typename InputIterator
// Doxygen doesn't understand this template wizardry
#if !defined(DOXYGEN)
# if !defined(DOXYGEN)
,
typename std::enable_if_t<
std::is_convertible<decltype(std::get<0>(*std::declval<InputIterator>())),
Expand All @@ -105,7 +105,7 @@ struct Struct
Value>::value

> * = nullptr
#endif
# endif
>
Struct(InputIterator it, InputIterator end) : Struct()
{
Expand Down Expand Up @@ -576,7 +576,7 @@ class ComponentInstance : vtable::Dyn
cbindgen_private::slint_run_event_loop();
hide();
}
#if defined(SLINT_QT_INTEGRATION) || defined(DOXYGEN)
# if defined(SLINT_FEATURE_BACKEND_QT) || defined(DOXYGEN)
/// Return a QWidget for this instance.
/// This function is only available if the qt graphical backend was compiled in, and
/// it may return nullptr if the Qt backend is not used at runtime.
Expand All @@ -588,7 +588,7 @@ class ComponentInstance : vtable::Dyn
reinterpret_cast<const cbindgen_private::WindowAdapterRc *>(win_ptr)));
return wid;
}
#endif
# endif

/// Set the value for a public property of this component
///
Expand Down Expand Up @@ -1029,3 +1029,5 @@ inline void send_keyboard_string_sequence(const slint::interpreter::ComponentIns
&str, reinterpret_cast<const cbindgen_private::WindowAdapterRc *>(win_ptr));
}
}

#endif
3 changes: 2 additions & 1 deletion api/cpp/include/slint_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

#pragma once

#include "slint.h"

#ifndef SLINT_FEATURE_EXPERIMENTAL
# warning "slint_platform.h API only available when SLINT_FEATURE_EXPERIMENTAL is activated"
#else

# include "slint.h"
# include <utility>

struct xcb_connection_t;
Expand Down
5 changes: 3 additions & 2 deletions xtask/src/cppdocs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ pub fn generate(show_warnings: bool) -> Result<(), Box<dyn std::error::Error>> {
)?;

let generated_headers_dir = docs_build_dir.join("generated_include");
let include_interpreter = true;
cbindgen::gen_all(&root, &generated_headers_dir, include_interpreter)?;
let enabled_features =
cbindgen::EnabledFeatures { interpreter: true, experimental: false, backend_qt: false };
cbindgen::gen_all(&root, &generated_headers_dir, enabled_features)?;

let pip_env = vec![(OsString::from("PIPENV_PIPFILE"), docs_source_dir.join("docs/Pipfile"))];

Expand Down

0 comments on commit a1bf773

Please sign in to comment.