Skip to content

Commit

Permalink
Move all type definitions to the ddcommon header
Browse files Browse the repository at this point in the history
  • Loading branch information
paullegranddc committed Jun 15, 2022
1 parent a000f1e commit ffcb1e7
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 8 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"ddcommon",
"ddcommon-ffi",
"ddtelemetry",
"tools",
]
# https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2
resolver = "2"
Expand Down
35 changes: 35 additions & 0 deletions ddcommon-ffi/cbindgen.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
# This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.

language = "C"
tab_width = 2
header = """// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.
"""
include_guard = "DDCOMMON_FFI_H"
style = "both"

no_includes = true
sys_includes = ["stdbool.h", "stddef.h", "stdint.h"]

after_includes = """
#define DDPROF_FFI_CHARSLICE_C(string) \\
/* NOTE: Compilation fails if you pass in a char* instead of a literal */ ((ddprof_ffi_CharSlice) {.ptr = "" string, .len = sizeof(string) - 1})"""

[export]
prefix = "ddprof_ffi_"

[export.mangle]
rename_types="SnakeCase"

[enum]
prefix_with_name = true
rename_variants = "ScreamingSnakeCase"

[fn]
must_use = "__attribute__((warn_unused_result))"

[parse]
parse_deps = true
include = ["ddcommon"]
8 changes: 2 additions & 6 deletions ddprof-ffi/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ style = "both"

no_includes = true
sys_includes = ["stdbool.h", "stddef.h", "stdint.h"]

after_includes = """
#define DDPROF_FFI_CHARSLICE_C(string) \\
/* NOTE: Compilation fails if you pass in a char* instead of a literal */ ((ddprof_ffi_CharSlice) {.ptr = "" string, .len = sizeof(string) - 1})"""
includes = ["libdatadog/ddcommon.h"]

[export]
prefix = "ddprof_ffi_"
Expand All @@ -32,4 +28,4 @@ must_use = "__attribute__((warn_unused_result))"

[parse]
parse_deps = true
include = ["ddcommon", "ddprof-exporter", "ddprof-profiles", "ux"]
include = ["ddcommon", "ddcommon-ffi", "ddprof-exporter", "ddprof-profiles", "ux"]
3 changes: 2 additions & 1 deletion examples/ffi/profiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
// developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present
// Datadog, Inc.

#include <ddprof/ffi.h>
#include <libdatadog/ddcommon.h>
#include <libdatadog/ddprof.h>
#include <stdint.h>

/* Creates a profile with one sample type "wall-time" with period of "wall-time"
Expand Down
7 changes: 6 additions & 1 deletion ffi-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,13 @@ if [ -n "$unexpected_native_libs" ]; then
fi
cd -

echo "Building tools"
cargo build --package tools --bins

echo "Generating the ddprof/ffi.h header..."
cbindgen --crate ddprof-ffi --config ddprof-ffi/cbindgen.toml --output "$destdir/include/ddprof/ffi.h"
cbindgen --crate ddcommon-ffi --config ddcommon-ffi/cbindgen.toml --output "$destdir/include/libdatadog/ddcommon.h"
cbindgen --crate ddprof-ffi --config ddprof-ffi/cbindgen.toml --output "$destdir/include/libdatadog/ddprof.h"
./target/debug/dedup_headers "$destdir/include/libdatadog/ddcommon.h" "$destdir/include/libdatadog/ddprof.h"

# CI doesn't have any clang tooling
# clang-format -i "$destdir/include/ddprof/ffi.h"
Expand Down
16 changes: 16 additions & 0 deletions tools/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
# This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.

[package]
name = "tools"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
regex = "1"
lazy_static = "1.4"

[[bin]]
name = "dedup_headers"
105 changes: 105 additions & 0 deletions tools/src/bin/dedup_headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.

/// Usage:
/// ./dedup_headers <base_header> <child_headers>...
///
/// All type definitions will be removed from the child_headers, and moved to the base_header
/// if they are not already defined in the parent_header
use regex::{Match, Regex, RegexBuilder};
use std::collections::HashSet;
use std::fs::{File, OpenOptions};
use std::io::{self, BufReader, BufWriter, Read, Seek, Write};

fn collect_definitions(header: &str) -> Vec<regex::Match<'_>> {
lazy_static::lazy_static! {
static ref HEADER_TYPE_DECL_RE: Regex = RegexBuilder::new(r"^(/\*.*?\*/\n)?typedef (struct|enum) [a-zA-Z_0-9]+ +(\{.*?\} )?[a-zA-Z_0-9]+;\n+")
.multi_line(true)
.dot_matches_new_line(true)
.build()
.unwrap();
}
HEADER_TYPE_DECL_RE.find_iter(header).collect()
}

fn read(f: &mut BufReader<&File>, until: Option<usize>) -> String {
let mut s = Vec::new();
match until {
Some(until) => {
s.resize(until, 0);
f.read_exact(&mut s).unwrap()
}
None => {
f.read_to_end(&mut s).unwrap();
}
};

String::from_utf8(s).unwrap()
}

fn write_parts(writer: &mut BufWriter<&File>, parts: &[&str]) -> io::Result<()> {
writer.get_ref().set_len(0)?;
writer.seek(io::SeekFrom::Start(0))?;
for part in parts {
writer.write_all(part.as_bytes())?;
}
Ok(())
}

fn content_without_defs<'a>(content: &'a str, defs: &[Match]) -> Vec<&'a str> {
let mut new_content_parts = Vec::new();
let mut pos = 0;
for d in defs {
new_content_parts.push(&content[pos..d.start()]);
pos = d.end();
}
new_content_parts.push(&content[pos..]);
new_content_parts
}

fn main() {
let args: Vec<_> = std::env::args_os().collect();

let mut unique_child_defs: Vec<String> = Vec::new();
let mut present = HashSet::new();
for child_def in args[2..].iter().flat_map(|p| {
let child_header = OpenOptions::new().read(true).write(true).open(p).unwrap();

let child_header_content = read(&mut BufReader::new(&child_header), None);
let child_defs = collect_definitions(&child_header_content);
let new_content_parts = content_without_defs(&child_header_content, &child_defs);

write_parts(&mut BufWriter::new(&child_header), &new_content_parts).unwrap();

child_defs
.into_iter()
.map(|m| m.as_str().to_owned())
.collect::<Vec<_>>()
}) {
if present.contains(&child_def) {
continue;
}
unique_child_defs.push(child_def.clone());
present.insert(child_def);
}

let base_header = OpenOptions::new()
.read(true)
.write(true)
.open(&args[1])
.unwrap();
let base_header_content = read(&mut BufReader::new(&base_header), None);
let base_defs = collect_definitions(&base_header_content);
let base_defs_set: HashSet<_> = base_defs.iter().map(Match::as_str).collect();

let mut base_new_parts = vec![&base_header_content[..base_defs.last().unwrap().end()]];

for child_def in &unique_child_defs {
if base_defs_set.contains(child_def.as_str()) {
continue;
}
base_new_parts.push(child_def);
}
base_new_parts.push(&base_header_content[base_defs.last().unwrap().end()..]);
write_parts(&mut BufWriter::new(&base_header), &base_new_parts).unwrap();
}
2 changes: 2 additions & 0 deletions tools/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.

0 comments on commit ffcb1e7

Please sign in to comment.