@@ -16,6 +16,10 @@ use std::process::Command;
1616use bindgen:: Abi ;
1717use once_cell:: sync:: Lazy ;
1818
19+ // Changing this part or build.rs in general runs a "build duckdb from source"
20+ // job in the CI, with all dependencies and benchmarks using this source-based build.
21+ // It's not ideal, but allows us to check pre-release stuff for breaking things or performance
22+ // regressions.
1923static DUCKDB_VERSION : Lazy < DuckDBVersion > = Lazy :: new ( || {
2024 // Override the DuckDB version via environment variable in case of an extension build.
2125 // `DUCKDB_VERSION` is set by the extension build in the `duckdb-vortex` repo.
@@ -252,7 +256,15 @@ fn extract_duckdb_source(source_dir: &Path) -> Result<PathBuf, Box<dyn std::erro
252256}
253257
254258/// Build DuckDB from source. Used for commit hashes or when VX_DUCKDB_DEBUG is set.
255- fn build_duckdb ( duckdb_source_dir : & Path ) -> Result < PathBuf , Box < dyn std:: error:: Error > > {
259+ fn build_duckdb (
260+ duckdb_source_dir : & Path ,
261+ version : & DuckDBVersion ,
262+ debug : bool ,
263+ ) -> Result < PathBuf , Box < dyn std:: error:: Error > > {
264+ let build_type = match debug {
265+ true => "debug" ,
266+ false => "release" ,
267+ } ;
256268 // Check for ninja
257269 if Command :: new ( "ninja" ) . arg ( "--version" ) . output ( ) . is_err ( ) {
258270 return Err (
@@ -262,10 +274,12 @@ fn build_duckdb(duckdb_source_dir: &Path) -> Result<PathBuf, Box<dyn std::error:
262274
263275 let inner_dir_name = DUCKDB_VERSION . archive_inner_dir_name ( ) ;
264276 let duckdb_repo_dir = duckdb_source_dir. join ( & inner_dir_name) ;
265- let build_dir = duckdb_repo_dir. join ( "build" ) . join ( "debug" ) ;
277+ let build_dir = duckdb_repo_dir. join ( "build" ) . join ( build_type ) ;
266278
267- // Check if already built
268279 let lib_dir = build_dir. join ( "src" ) ;
280+ let lib_dir_str = lib_dir. display ( ) ;
281+ println ! ( "cargo:info=Checking if DuckDB is already built in {lib_dir_str}" , ) ;
282+
269283 let already_built = lib_dir. join ( "libduckdb.dylib" ) . exists ( )
270284 || lib_dir. join ( "libduckdb.so" ) . exists ( )
271285 || lib_dir
@@ -286,12 +300,26 @@ fn build_duckdb(duckdb_source_dir: &Path) -> Result<PathBuf, Box<dyn std::error:
286300 ( "1" , "0" )
287301 } ;
288302
303+ let mut envs = vec ! [
304+ ( "GEN" , "ninja" ) ,
305+ ( "DISABLE_SANITIZER" , asan_option) ,
306+ ( "THREADSAN" , tsan_option) ,
307+ ( "BUILD_SHELL" , "false" ) ,
308+ ( "BUILD_UNITTESTS" , "false" ) ,
309+ ( "ENABLE_UNITTEST_CPP_TESTS" , "false" ) ,
310+ ] ;
311+
312+ // If we're building from a commit (likely a pre-release), we need to
313+ // build extensions statically. Otherwise DuckDB tries to load them
314+ // from an http endpoint with version 0.0.1 (all non-tagged builds)
315+ // which doesn't exists. httpfs also requires CURL dev headers
316+ if matches ! ( version, DuckDBVersion :: Commit ( _) ) {
317+ envs. push ( ( "BUILD_EXTENSIONS" , "httpfs;parquet;tpch;tpcds;jemalloc" ) ) ;
318+ } ;
319+
289320 let output = Command :: new ( "make" )
290321 . current_dir ( & duckdb_repo_dir)
291- . env ( "GEN" , "ninja" )
292- . env ( "DISABLE_SANITIZER" , asan_option)
293- . env ( "THREADSAN" , tsan_option)
294- . arg ( "debug" )
322+ . envs ( envs)
295323 . output ( ) ?;
296324
297325 if !output. status . success ( ) {
@@ -375,15 +403,21 @@ fn main() {
375403 drop ( fs:: remove_dir_all ( & duckdb_symlink) ) ;
376404 std:: os:: unix:: fs:: symlink ( & extracted_source_path, & duckdb_symlink) . unwrap ( ) ;
377405
378- // Determine whether to build from source or use prebuilt libraries
379406 let use_debug_build =
380407 env:: var ( "VX_DUCKDB_DEBUG" ) . is_ok_and ( |v| matches ! ( v. as_str( ) , "1" | "true" ) ) ;
408+ println ! ( "cargo:info=DuckDB debug build: {use_debug_build}" ) ;
381409
382410 let library_path = if use_debug_build || !DUCKDB_VERSION . is_release ( ) {
383411 // Build from source for:
384412 // - Commit hashes (no prebuilt available)
385413 // - When VX_DUCKDB_DEBUG=1 (user wants debug build)
386- build_duckdb ( & extracted_source_path) . unwrap ( )
414+ match build_duckdb ( & extracted_source_path, & DUCKDB_VERSION , use_debug_build) {
415+ Ok ( path) => path,
416+ Err ( err) => {
417+ println ! ( "cargo:error={err}" ) ;
418+ panic ! ( "duckdb build failed" ) ;
419+ }
420+ }
387421 } else {
388422 // Download prebuilt libraries for release versions
389423 let archive_path = download_duckdb_lib_archive ( ) . unwrap ( ) ;
0 commit comments