Skip to content

Commit 2573424

Browse files
fix: remove 'default-members' in workspace, default to all crates (#752)
**Problem:** new contributors have compilation errors which aren't raised when they run a normal `cargo test` or `cargo nextest run` since FFI crate (among others) aren't built by default. **Solution:** remove `default-members = ["acceptance", "kernel"]` in our workspace's `Cargo.toml` in order to default to building all crates. This PR includes the update above + some fixes for docs, clippy, etc. and modifies how we run `clippy --no-default-features` in CI so that we _actually_ check kernel without any features enabled.
1 parent ec47584 commit 2573424

File tree

11 files changed

+70
-24
lines changed

11 files changed

+70
-24
lines changed

.github/workflows/build.yml

+26-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,28 @@ jobs:
6969
- name: build docs
7070
run: cargo doc
7171

72+
73+
# When we run cargo { build, clippy } --no-default-features, we want to build/lint the kernel to
74+
# ensure that we can build the kernel without any features enabled. Unfortunately, due to how
75+
# cargo resolves features, if we have a workspace member that depends on the kernel with features
76+
# enabled, the kernel will be compiled with those features (even if we specify
77+
# --no-default-features).
78+
#
79+
# To cope with this, we split build/clippy --no-default-features into two runs:
80+
# 1. build/clippy all packages that depend on the kernel with some features enabled:
81+
# - acceptance
82+
# - test_utils
83+
# - feature_tests
84+
# (and examples)
85+
# - inspect-table
86+
# - read-table-changes
87+
# - read-table-multi-threaded
88+
# - read-table-single-threaded
89+
# 2. build/clippy all packages that only have no-feature kernel dependency
90+
# - delta_kernel
91+
# - delta_kernel_derive
92+
# - delta_kernel_ffi
93+
# - delta_kernel_ffi_macros
7294
build:
7395
runs-on: ${{ matrix.os }}
7496
strategy:
@@ -85,8 +107,10 @@ jobs:
85107
components: clippy
86108
- name: build and lint with clippy
87109
run: cargo clippy --benches --tests --all-features -- -D warnings
88-
- name: lint without default features
89-
run: cargo clippy --no-default-features -- -D warnings
110+
- name: lint without default features - packages which depend on kernel with features enabled
111+
run: cargo clippy --workspace --no-default-features --exclude delta_kernel --exclude delta_kernel_ffi --exclude delta_kernel_derive --exclude delta_kernel_ffi_macros -- -D warnings
112+
- name: lint without default features - packages which don't depend on kernel with features enabled
113+
run: cargo clippy --no-default-features --package delta_kernel --package delta_kernel_ffi --package delta_kernel_derive --package delta_kernel_ffi_macros -- -D warnings
90114
- name: check kernel builds with default-engine
91115
run: cargo build -p feature_tests --features default-engine
92116
- name: check kernel builds with default-engine-rustls

Cargo.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ members = [
88
"test-utils",
99
"feature-tests",
1010
]
11-
# Only check / build main crates by default (check all with `--workspace`)
12-
default-members = ["acceptance", "kernel"]
11+
# note that in addition to the members above, the workspace includes examples:
12+
# - inspect-table
13+
# - read-table-changes
14+
# - read-table-multi-threaded
15+
# - read-table-single-threaded
1316
resolver = "2"
1417

1518
[workspace.package]

ffi/Cargo.toml

+2-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ tracing-core = { version = "0.1", optional = true }
2222
tracing-subscriber = { version = "0.3", optional = true, features = [ "json" ] }
2323
url = "2"
2424
delta_kernel = { path = "../kernel", default-features = false, features = [
25-
"arrow",
2625
"developer-visibility",
2726
] }
2827
delta_kernel_ffi_macros = { path = "../ffi-proc-macros", version = "0.8.0" }
@@ -32,7 +31,6 @@ cbindgen = "0.28"
3231
libc = "0.2.158"
3332

3433
[dev-dependencies]
35-
delta_kernel = { path = "../kernel", features = ["default-engine", "sync-engine"] }
3634
object_store = { workspace = true }
3735
rand = "0.8.5"
3836
test_utils = { path = "../test-utils" }
@@ -42,10 +40,8 @@ trybuild = "1.0"
4240
[features]
4341
default = ["default-engine"]
4442
cloud = ["delta_kernel/cloud"]
45-
default-engine = [
46-
"delta_kernel/default-engine",
47-
]
43+
default-engine = ["delta_kernel/default-engine", "delta_kernel/arrow"]
4844
tracing = [ "tracing-core", "tracing-subscriber" ]
49-
sync-engine = ["delta_kernel/sync-engine"]
45+
sync-engine = ["delta_kernel/sync-engine", "delta_kernel/arrow"]
5046
developer-visibility = []
5147
test-ffi = []

ffi/src/engine_data.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
//! EngineData related ffi code
22
3+
#[cfg(feature = "default-engine")]
34
use delta_kernel::arrow::array::{
45
ffi::{FFI_ArrowArray, FFI_ArrowSchema},
56
ArrayData, StructArray,
67
};
7-
use delta_kernel::{DeltaResult, EngineData};
8+
#[cfg(feature = "default-engine")]
9+
use delta_kernel::DeltaResult;
10+
use delta_kernel::EngineData;
811
use std::ffi::c_void;
912

10-
use crate::{ExclusiveEngineData, ExternResult, IntoExternResult, SharedExternEngine};
13+
use crate::ExclusiveEngineData;
14+
#[cfg(feature = "default-engine")]
15+
use crate::{ExternResult, IntoExternResult, SharedExternEngine};
1116

1217
use super::handle::Handle;
1318

ffi/src/engine_funcs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ impl Drop for FileReadResultIterator {
5454
///
5555
/// The iterator must be valid (returned by [`read_parquet_file`]) and not yet freed by
5656
/// [`free_read_result_iter`]. The visitor function pointer must be non-null.
57+
///
58+
/// [`free_engine_data`]: crate::free_engine_data
5759
#[no_mangle]
5860
pub unsafe extern "C" fn read_result_next(
5961
mut data: Handle<ExclusiveFileReadResultIterator>,

ffi/src/expressions/engine.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ impl KernelExpressionVisitorState {
2828
///
2929
/// When invoking [`scan::scan`], The engine provides a pointer to the (engine's native) predicate,
3030
/// along with a visitor function that can be invoked to recursively visit the predicate. This
31-
/// engine state must be valid until the call to `scan::scan` returns. Inside that method, the
31+
/// engine state must be valid until the call to [`scan::scan`] returns. Inside that method, the
3232
/// kernel allocates visitor state, which becomes the second argument to the predicate visitor
3333
/// invocation along with the engine-provided predicate pointer. The visitor state is valid for the
3434
/// lifetime of the predicate visitor invocation. Thanks to this double indirection, engine and
3535
/// kernel each retain ownership of their respective objects, with no need to coordinate memory
3636
/// lifetimes with the other.
37+
///
38+
/// [`scan::scan`]: crate::scan::scan
3739
#[repr(C)]
3840
pub struct EnginePredicate {
3941
pub predicate: *mut c_void,

ffi/src/expressions/kernel.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ type VisitUnaryFn = extern "C" fn(data: *mut c_void, sibling_list_id: usize, chi
5353
/// WARNING: The visitor MUST NOT retain internal references to string slices or binary data passed
5454
/// to visitor methods
5555
/// TODO: Visit type information in struct field and null. This will likely involve using the schema
56-
/// visitor. Note that struct literals are currently in flux, and may change significantly. Here is the relevant
57-
/// issue: https://github.com/delta-io/delta-kernel-rs/issues/412
56+
/// visitor. Note that struct literals are currently in flux, and may change significantly. Here is
57+
/// the relevant issue: <https://github.com/delta-io/delta-kernel-rs/issues/412>
5858
#[repr(C)]
5959
pub struct EngineExpressionVisitor {
6060
/// An opaque engine state pointer

ffi/src/handle.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ mod private {
8888
/// Additionally, in keeping with the [`Send`] contract, multi-threaded external code must
8989
/// enforce mutual exclusion -- no mutable handle should ever be passed to more than one kernel
9090
/// API call at a time. If thread races are possible, the handle should be protected with a
91-
/// mutex. Due to Rust [reference
92-
/// rules](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references),
93-
/// this requirement applies even for API calls that appear to be read-only (because Rust code
94-
/// always receives the handle as mutable).
91+
/// mutex. Due to Rust [reference rules], this requirement applies even for API calls that
92+
/// appear to be read-only (because Rust code always receives the handle as mutable).
9593
///
9694
/// NOTE: Because the underlying type is always [`Sync`], multi-threaded external code can
9795
/// freely access shared (non-mutable) handles.
9896
///
97+
/// [reference rules]:
98+
/// https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references
9999
/// cbindgen:transparent-typedef
100100
#[repr(transparent)]
101101
pub struct Handle<H: HandleDescriptor> {

ffi/src/lib.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl Iterator for EngineIterator {
8181
///
8282
/// Whoever instantiates the struct must ensure it does not outlive the data it points to. The
8383
/// compiler cannot help us here, because raw pointers don't have lifetimes. A good rule of thumb is
84-
/// to always use the [`kernel_string_slice`] macro to create string slices, and to avoid returning
84+
/// to always use the `kernel_string_slice` macro to create string slices, and to avoid returning
8585
/// a string slice from a code block or function (since the move risks over-extending its lifetime):
8686
///
8787
/// ```ignore
@@ -331,6 +331,8 @@ pub unsafe extern "C" fn free_row_indexes(slice: KernelRowIndexArray) {
331331
/// an opaque struct that encapsulates data read by an engine. this handle can be passed back into
332332
/// some kernel calls to operate on the data, or can be converted into the raw data as read by the
333333
/// [`delta_kernel::Engine`] by calling [`get_raw_engine_data`]
334+
///
335+
/// [`get_raw_engine_data`]: crate::engine_data::get_raw_engine_data
334336
#[handle_descriptor(target=dyn EngineData, mutable=true)]
335337
pub struct ExclusiveEngineData;
336338

@@ -353,12 +355,14 @@ pub trait ExternEngine: Send + Sync {
353355
#[handle_descriptor(target=dyn ExternEngine, mutable=false)]
354356
pub struct SharedExternEngine;
355357

358+
#[cfg(any(feature = "default-engine", feature = "sync-engine"))]
356359
struct ExternEngineVtable {
357360
// Actual engine instance to use
358361
engine: Arc<dyn Engine>,
359362
allocate_error: AllocateErrorFn,
360363
}
361364

365+
#[cfg(any(feature = "default-engine", feature = "sync-engine"))]
362366
impl Drop for ExternEngineVtable {
363367
fn drop(&mut self) {
364368
debug!("dropping engine interface");
@@ -369,6 +373,7 @@ impl Drop for ExternEngineVtable {
369373
///
370374
/// Kernel doesn't use any threading or concurrency. If engine chooses to do so, engine is
371375
/// responsible for handling any races that could result.
376+
#[cfg(any(feature = "default-engine", feature = "sync-engine"))]
372377
unsafe impl Send for ExternEngineVtable {}
373378

374379
/// # Safety
@@ -380,8 +385,10 @@ unsafe impl Send for ExternEngineVtable {}
380385
/// Basically, by failing to implement these traits, we forbid the engine from being able to declare
381386
/// its thread-safety (because rust assumes it is not threadsafe). By implementing them, we leave it
382387
/// up to the engine to enforce thread safety if engine chooses to use threads at all.
388+
#[cfg(any(feature = "default-engine", feature = "sync-engine"))]
383389
unsafe impl Sync for ExternEngineVtable {}
384390

391+
#[cfg(any(feature = "default-engine", feature = "sync-engine"))]
385392
impl ExternEngine for ExternEngineVtable {
386393
fn engine(&self) -> Arc<dyn Engine> {
387394
self.engine.clone()
@@ -677,8 +684,11 @@ pub struct StringSliceIterator;
677684

678685
/// # Safety
679686
///
680-
/// The iterator must be valid (returned by [kernel_scan_data_init]) and not yet freed by
681-
/// [kernel_scan_data_free]. The visitor function pointer must be non-null.
687+
/// The iterator must be valid (returned by [`kernel_scan_data_init`]) and not yet freed by
688+
/// [`free_kernel_scan_data`]. The visitor function pointer must be non-null.
689+
///
690+
/// [`kernel_scan_data_init`]: crate::scan::kernel_scan_data_init
691+
/// [`free_kernel_scan_data`]: crate::scan::free_kernel_scan_data
682692
#[no_mangle]
683693
pub unsafe extern "C" fn string_slice_next(
684694
data: Handle<StringSliceIterator>,

ffi/src/scan.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ use super::handle::Handle;
3030
pub struct SharedScan;
3131

3232
/// Drops a scan.
33+
///
3334
/// # Safety
34-
/// Caller is responsible for passing a [valid][Handle#Validity] scan handle.
35+
/// Caller is responsible for passing a valid scan handle.
3536
#[no_mangle]
3637
pub unsafe extern "C" fn free_scan(scan: Handle<SharedScan>) {
3738
scan.drop_handle();
@@ -182,6 +183,9 @@ fn kernel_scan_data_init_impl(
182183
///
183184
/// The iterator must be valid (returned by [kernel_scan_data_init]) and not yet freed by
184185
/// [`free_kernel_scan_data`]. The visitor function pointer must be non-null.
186+
///
187+
/// [`free_bool_slice`]: crate::free_bool_slice
188+
/// [`free_engine_data`]: crate::free_engine_data
185189
#[no_mangle]
186190
pub unsafe extern "C" fn kernel_scan_data_next(
187191
data: Handle<SharedScanDataIterator>,

test-utils/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ version.workspace = true
1212
release = false
1313

1414
[dependencies]
15-
delta_kernel = { path = "../kernel", features = [ "default-engine", "arrow" ] }
15+
delta_kernel = { path = "../kernel", features = [ "default-engine", "arrow" ] }
1616
itertools = "0.13.0"
1717
object_store = { workspace = true }

0 commit comments

Comments
 (0)