Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 49 additions & 13 deletions vortex-duckdb/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use std::env;
use std::fs;
use std::io;
#[cfg(unix)]
use std::os::unix::fs::symlink;
use std::path::Path;
use std::path::PathBuf;
Expand All @@ -22,7 +23,12 @@ const DUCKDB_SOURCE_RELEASE_URL: &str = "https://github.com/duckdb/duckdb/archiv
const DUCKDB_SOURCE_COMMIT_URL: &str = "https://github.com/duckdb/duckdb/archive";
const DEFAULT_DUCKDB_VERSION: &str = "1.5.3";

const BUILD_ARTIFACTS: [&str; 3] = ["libduckdb.dylib", "libduckdb.so", "libduckdb_static.a"];
const BUILD_ARTIFACTS: [&str; 4] = [
"libduckdb.dylib",
"libduckdb.so",
"libduckdb_static.a",
"duckdb.dll",
];

const SOURCE_FILES: [&str; 17] = [
"cpp/client_context.cpp",
Expand Down Expand Up @@ -178,6 +184,8 @@ fn download(version: &DuckDBVersion, library_dir: &Path) {
"aarch64-apple-darwin" | "x86_64-apple-darwin" => ("osx", "universal"),
"x86_64-unknown-linux-gnu" => ("linux", "amd64"),
"aarch64-unknown-linux-gnu" => ("linux", "arm64"),
"x86_64-pc-windows-msvc" => ("windows", "amd64"),
"aarch64-pc-windows-msvc" => ("windows", "arm64"),
_ => {
println!("cargo:error=Unsupported target {target}");
exit(1);
Expand Down Expand Up @@ -353,13 +361,21 @@ fn bindgen_c2rust(crate_dir: &Path, duckdb_include_dir: &Path) {

/// Generate libvortex_duckdb.*
fn compile_cpp(duckdb_include_dir: &Path) {
cc::Build::new()
.std("c++20")
.flags(["-Wall", "-Wextra", "-Wpedantic", "-Werror"])
.cpp(true)
// We don't want compiler warnings inside duckdb headers, pass as flags
.flag("-isystem")
.flag(duckdb_include_dir)
let mut build = cc::Build::new();
build.std("c++20").cpp(true);
if env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("msvc") {
// MSVC's `cl` does not understand the GCC/Clang `-W*`/`-isystem` flags. Use the
// `/W4` warning level and add the DuckDB headers as a normal include. We do not
// enable `/WX`, so warnings originating in those headers don't fail the build.
build.flag("/W4").include(duckdb_include_dir);
} else {
build
.flags(["-Wall", "-Wextra", "-Wpedantic", "-Werror"])
// We don't want compiler warnings inside duckdb headers, pass as flags
.flag("-isystem")
.flag(duckdb_include_dir);
}
build
.include("include")
.include("cpp/include")
.files(SOURCE_FILES)
Expand Down Expand Up @@ -396,6 +412,21 @@ fn cbindgen_rust2c(crate_dir: &Path) {
}
}

/// Create a convenience symlink from `duckdb_dir` to the extracted DuckDB source tree.
/// This is purely for editor/tooling navigation; the build uses the source path directly.
/// Only created on unix, where the symlink API needs no special privilege.
#[cfg(unix)]
fn symlink_duckdb_source(source_dir: &Path, duckdb_dir: &Path) {
drop(fs::remove_file(duckdb_dir));
drop(fs::remove_dir_all(duckdb_dir));
symlink(source_dir, duckdb_dir).unwrap();
}

/// No-op on non-unix platforms (e.g. Windows): the symlink is only a convenience and
/// Windows directory symlinks require elevated privileges.
#[cfg(not(unix))]
fn symlink_duckdb_source(_source_dir: &Path, _duckdb_dir: &Path) {}

fn main() {
println!("cargo:rerun-if-env-changed=DUCKDB_VERSION");
println!("cargo:rerun-if-env-changed=VX_DUCKDB_DEBUG");
Expand Down Expand Up @@ -427,8 +458,12 @@ fn main() {
println!("cargo:rustc-link-lib=dylib=duckdb");

// Set rpath for binaries built directly from this crate. This is not
// inherited by downstream crates.
println!("cargo:rustc-link-arg=-Wl,-rpath,{library_dir_str}");
// inherited by downstream crates. `-Wl,-rpath` is GNU/Clang linker syntax that
// MSVC's linker rejects; on Windows the DLL is resolved via PATH / the executable
// directory instead, so skip it there.
if env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("windows") {
println!("cargo:rustc-link-arg=-Wl,-rpath,{library_dir_str}");
}

// Export the library path for downstream crates via the `links` manifest key.
// Downstream crates can access this via `env::var("DEP_DUCKDB_LIB_DIR")` in their build.rs
Expand Down Expand Up @@ -467,9 +502,10 @@ fn main() {
fs::write(&extract_marker, version.to_string()).unwrap();
}

drop(fs::remove_file(&duckdb_dir));
drop(fs::remove_dir_all(&duckdb_dir));
symlink(&source_dir, &duckdb_dir).unwrap();
// Convenience symlink `crate_dir/duckdb` -> extracted source, for editor/tooling
// navigation only; the build itself uses `inner_dir` below. Created on unix where
// the symlink API is privilege-free; skipped elsewhere (e.g. Windows).
symlink_duckdb_source(&source_dir, &duckdb_dir);

let has_debug_env =
env::var("VX_DUCKDB_DEBUG").is_ok_and(|v| matches!(v.as_str(), "1" | "true"));
Expand Down
Loading