Remove some duplication in the documentation of API that's shared between Rust and C++

This change makes the start of sharing the docs for the `TimerMode` enum
between Rust and C++. The reference to Timer::start in there works as
both doxygen and rustdoc find the right reference, but this needs
careful editing in the future and double-checking!

Another "caveat" is that the docs for the TimerMode enum say that the
enum is defined in the file "sixtyfps_generated_public.h", which is
correct as-is but not as pretty as "sixtyfps.h". I tried various ways
with \file and \includedoc, but couldn't get it working differently.

To implement this, the cppdocs steps now also runs cbindgen and cbindgen
generates a new sixtyfps_generated_public.h file that contains types we
do want to have in the public sixtyfps namespace.
This commit is contained in:
Simon Hausmann 2022-01-05 14:40:17 +01:00 committed by Simon Hausmann
parent 81602353e2
commit 174fd2659f
6 changed files with 72 additions and 36 deletions

View file

@ -20,5 +20,9 @@ fn main() -> Result<(), anyhow::Error> {
println!("cargo:GENERATED_INCLUDE_DIR={}", output_dir.display());
cbindgen::gen_all(&root_dir, &output_dir)
let dependencies = cbindgen::gen_all(&root_dir, &output_dir)?;
for path in dependencies {
println!("cargo:rerun-if-changed={}", path.display());
}
Ok(())
}

View file

@ -3,16 +3,19 @@
use anyhow::Context;
use std::iter::Extend;
use std::path::Path;
use std::path::{Path, PathBuf};
// cspell::ignore compat constexpr corelib sharedvector pathdata
fn ensure_cargo_rerun_for_crate(crate_dir: &Path) -> anyhow::Result<()> {
println!("cargo:rerun-if-changed={}", crate_dir.display());
fn ensure_cargo_rerun_for_crate(
crate_dir: &Path,
dependencies: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
dependencies.push(crate_dir.to_path_buf());
for entry in std::fs::read_dir(crate_dir)? {
let entry = entry?;
if entry.path().extension().map_or(false, |e| e == "rs") {
println!("cargo:rerun-if-changed={}", entry.path().display());
dependencies.push(entry.path());
}
}
Ok(())
@ -76,7 +79,11 @@ extern "C" {{
)
}
fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
fn gen_corelib(
root_dir: &Path,
include_dir: &Path,
dependencies: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
let mut config = default_config();
let items = [
@ -150,6 +157,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
"sixtyfps_color_darker",
"sixtyfps_image_size",
"sixtyfps_image_path",
"TimerMode", // included in generated_public.h
]
.iter()
.map(|x| x.to_string())
@ -158,7 +166,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
let mut crate_dir = root_dir.to_owned();
crate_dir.extend(["sixtyfps_runtime", "corelib"].iter());
ensure_cargo_rerun_for_crate(&crate_dir)?;
ensure_cargo_rerun_for_crate(&crate_dir, dependencies)?;
let mut string_config = config.clone();
string_config.export.exclude = vec!["SharedString".into()];
@ -296,6 +304,20 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
.write_to_file(include_dir.join(internal_header));
}
// Generate a header file with some public API (enums, etc.)
let mut public_config = config.clone();
public_config.namespaces = Some(vec!["sixtyfps".into()]);
public_config.export.item_types = vec![cbindgen::ItemType::Enums];
public_config.export.include = vec!["TimerMode".into()];
public_config.export.exclude.clear();
cbindgen::Builder::new()
.with_config(public_config)
.with_src(crate_dir.join("timers.rs"))
.generate()
.context("Unable to generate bindings for sixtyfps_generated_public.h")?
.write_to_file(include_dir.join("sixtyfps_generated_public.h"));
config.export.body.insert(
"ItemTreeNode".to_owned(),
" constexpr ItemTreeNode(Item_Body x) : item {x} {}
@ -335,6 +357,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
.with_include("sixtyfps_image.h")
.with_include("sixtyfps_pathdata.h")
.with_include("sixtyfps_brush.h")
.with_include("sixtyfps_generated_public.h")
.with_header(format!(
r"
#define SIXTYFPS_VERSION_MAJOR {}
@ -367,7 +390,11 @@ namespace sixtyfps {
Ok(())
}
fn gen_backend_qt(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
fn gen_backend_qt(
root_dir: &Path,
include_dir: &Path,
dependencies: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
let mut config = default_config();
let items = [
@ -395,7 +422,7 @@ fn gen_backend_qt(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
let mut crate_dir = root_dir.to_owned();
crate_dir.extend(["sixtyfps_runtime", "rendering_backends", "qt"].iter());
ensure_cargo_rerun_for_crate(&crate_dir)?;
ensure_cargo_rerun_for_crate(&crate_dir, dependencies)?;
cbindgen::Builder::new()
.with_config(config)
@ -409,12 +436,16 @@ fn gen_backend_qt(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
Ok(())
}
fn gen_backend(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
fn gen_backend(
root_dir: &Path,
include_dir: &Path,
dependencies: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
let config = default_config();
let mut crate_dir = root_dir.to_owned();
crate_dir.extend(["api", "sixtyfps-cpp"].iter());
ensure_cargo_rerun_for_crate(&crate_dir)?;
ensure_cargo_rerun_for_crate(&crate_dir, dependencies)?;
cbindgen::Builder::new()
.with_config(config)
@ -427,14 +458,18 @@ fn gen_backend(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
Ok(())
}
fn gen_interpreter(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
fn gen_interpreter(
root_dir: &Path,
include_dir: &Path,
dependencies: &mut Vec<PathBuf>,
) -> anyhow::Result<()> {
let mut config = default_config();
// Avoid Value, just export ValueOpaque.
config.export.exclude.push("Value".into());
let mut crate_dir = root_dir.to_owned();
crate_dir.extend(["sixtyfps_runtime", "interpreter"].iter());
ensure_cargo_rerun_for_crate(&crate_dir)?;
ensure_cargo_rerun_for_crate(&crate_dir, dependencies)?;
cbindgen::Builder::new()
.with_config(config)
@ -451,12 +486,15 @@ fn gen_interpreter(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
/// Generate the headers.
/// `root_dir` is the root directory of the sixtyfps git repo
/// `include_dir` is the output directory
pub fn gen_all(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
/// Returns the list of all paths that contain dependencies to the generated output. If you call this
/// function from build.rs, feed each entry to stdout prefixed with `cargo:rerun-if-changed=`.
pub fn gen_all(root_dir: &Path, include_dir: &Path) -> 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")?;
gen_corelib(root_dir, include_dir)?;
gen_backend_qt(root_dir, include_dir)?;
gen_backend(root_dir, include_dir)?;
gen_interpreter(root_dir, include_dir)?;
Ok(())
let mut deps = Vec::new();
gen_corelib(root_dir, include_dir, &mut deps)?;
gen_backend_qt(root_dir, include_dir, &mut deps)?;
gen_backend(root_dir, include_dir, &mut deps)?;
gen_interpreter(root_dir, include_dir, &mut deps)?;
Ok(deps)
}

View file

@ -56,8 +56,8 @@ exhale_args = {
"doxygenStripFromPath": "..",
"createTreeView": True,
"exhaleExecutesDoxygen": True,
"exhaleDoxygenStdin": """INPUT = ../../api/sixtyfps-cpp/include
EXCLUDE_SYMBOLS = sixtyfps::cbindgen_private* sixtyfps::private_api* vtable*
"exhaleDoxygenStdin": """INPUT = ../../api/sixtyfps-cpp/include generated_include
EXCLUDE_SYMBOLS = sixtyfps::cbindgen_private* sixtyfps::private_api* vtable* SIXTYFPS_DECL_ITEM
EXCLUDE = ../../api/sixtyfps-cpp/include/vtable.h ../../api/sixtyfps-cpp/include/sixtyfps_testing.h
ENABLE_PREPROCESSING = YES
PREDEFINED += DOXYGEN

View file

@ -337,20 +337,6 @@ private:
private_api::WindowRc inner;
};
#if !defined(DOXYGEN)
using cbindgen_private::TimerMode;
#else
/// The TimerMode specifies what should happen after the timer fired.
///
/// Used by the sixtyfps::Timer::start() function.
enum class TimerMode {
/// A SingleShot timer is fired only once.
SingleShot,
/// A Repeated timer is fired repeatedly until it is stopped or dropped.
Repeated,
};
#endif
/// A Timer that can call a callback at repeated interval
///
/// Use the static single_shot function to make a single shot timer
@ -367,7 +353,7 @@ struct Timer
template<typename F>
Timer(std::chrono::milliseconds interval, F callback)
: id(cbindgen_private::sixtyfps_timer_start(
-1, cbindgen_private::TimerMode::Repeated, interval.count(),
-1, TimerMode::Repeated, interval.count(),
[](void *data) { (*reinterpret_cast<F *>(data))(); }, new F(std::move(callback)),
[](void *data) { delete reinterpret_cast<F *>(data); }))
{