1+ use glob:: glob;
12use std:: env;
23use std:: ffi:: OsString ;
34use std:: fs:: { self , OpenOptions } ;
@@ -130,6 +131,57 @@ fn make_amalgamation() {
130131 . unwrap ( ) ;
131132}
132133
134+ fn generate_sqlean ( enabled_extensions : & [ & str ] , output_path : & Path ) -> io:: Result < ( ) > {
135+ let mut content = String :: from (
136+ r#"// Generated by build.rs
137+
138+
139+ #include "sqlite3.c"
140+ SQLITE_EXTENSION_INIT1
141+
142+ "# ,
143+ ) ;
144+
145+ for ext in enabled_extensions {
146+ content. push_str ( & format ! ( "#include \" {}/extension.h\" \n " , ext) ) ;
147+ }
148+
149+ content. push_str (
150+ r#"
151+ #include "sqlean.h"
152+
153+ static void sqlean_version(sqlite3_context* context, int argc, sqlite3_value** argv) {
154+ sqlite3_result_text(context, SQLEAN_VERSION, -1, SQLITE_STATIC);
155+ }
156+
157+ #ifdef _WIN32
158+ __declspec(dllexport)
159+ #endif
160+ int sqlite3_sqlean_init(sqlite3* db, char** errmsg_ptr, const sqlite3_api_routines* api) {
161+ (void)errmsg_ptr;
162+ SQLITE_EXTENSION_INIT2(api);
163+ static const int flags = SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC;
164+ sqlite3_create_function(db, "sqlean_version", 0, flags, 0, sqlean_version, 0, 0);
165+ "# ,
166+ ) ;
167+
168+ for ext in enabled_extensions {
169+ content. push_str ( & format ! ( " {}_init(db);\n " , ext) ) ;
170+ }
171+
172+ content. push_str (
173+ r#" return SQLITE_OK;
174+ }
175+
176+ int core_init(const char* dummy) {
177+ return sqlite3_auto_extension((void*)sqlite3_sqlean_init);
178+ }
179+ "# ,
180+ ) ;
181+
182+ std:: fs:: write ( output_path, content)
183+ }
184+
133185pub fn build_bundled ( out_dir : & str , out_path : & Path ) {
134186 let bindgen_rs_path = if cfg ! ( feature = "session" ) {
135187 "bundled/bindings/session_bindgen.rs"
@@ -146,8 +198,7 @@ pub fn build_bundled(out_dir: &str, out_path: &Path) {
146198 std:: fs:: copy ( format ! ( "{dir}/{bindgen_rs_path}" ) , out_path) . unwrap ( ) ;
147199
148200 let mut cfg = cc:: Build :: new ( ) ;
149- cfg. file ( format ! ( "{BUNDLED_DIR}/src/sqlite3.c" ) )
150- . flag ( "-std=c11" )
201+ cfg. flag ( "-std=c11" )
151202 . flag ( "-DSQLITE_CORE" )
152203 . flag ( "-DSQLITE_DEFAULT_FOREIGN_KEYS=1" )
153204 . flag ( "-DSQLITE_ENABLE_API_ARMOR" )
@@ -169,6 +220,62 @@ pub fn build_bundled(out_dir: &str, out_path: &Path) {
169220 . flag ( "-D_POSIX_THREAD_SAFE_FUNCTIONS" ) // cross compile with MinGW
170221 . warnings ( false ) ;
171222
223+ let mut sqlean_patterns = vec ! [ ] ;
224+ let mut enabled_extensions = Vec :: new ( ) ;
225+
226+ if cfg ! ( feature = "sqlean-extension-crypto" ) {
227+ enabled_extensions. push ( "crypto" ) ;
228+ sqlean_patterns. push ( "crypto/*.c" ) ;
229+ }
230+
231+ if cfg ! ( feature = "sqlean-extension-fuzzy" ) {
232+ enabled_extensions. push ( "fuzzy" ) ;
233+ sqlean_patterns. push ( "fuzzy/*.c" ) ;
234+ }
235+
236+ if cfg ! ( feature = "sqlean-extension-math" ) {
237+ enabled_extensions. push ( "math" ) ;
238+ sqlean_patterns. push ( "math/*.c" ) ;
239+ }
240+
241+ if cfg ! ( feature = "sqlean-extension-stats" ) {
242+ enabled_extensions. push ( "stats" ) ;
243+ sqlean_patterns. push ( "stats/*.c" ) ;
244+ }
245+
246+ if cfg ! ( feature = "sqlean-extension-text" ) {
247+ enabled_extensions. push ( "text" ) ;
248+ sqlean_patterns. push ( "text/*.c" ) ;
249+ sqlean_patterns. push ( "text/*/*.c" ) ;
250+ }
251+
252+ if cfg ! ( feature = "sqlean-extension-uuid" ) {
253+ enabled_extensions. push ( "uuid" ) ;
254+ sqlean_patterns. push ( "uuid/*.c" ) ;
255+ }
256+
257+ if sqlean_patterns. is_empty ( ) {
258+ cfg. file ( format ! ( "{BUNDLED_DIR}/src/sqlite3.c" ) ) ;
259+ } else {
260+ cfg. flag ( "-DSQLITE_EXTRA_INIT=core_init" ) ;
261+
262+ let mut sqlean_sources = Vec :: new ( ) ;
263+ for pattern in sqlean_patterns {
264+ let full_pattern = format ! ( "{BUNDLED_DIR}/sqlean/{}" , pattern) ;
265+ sqlean_sources. extend ( glob ( & full_pattern) . unwrap ( ) . filter_map ( Result :: ok) ) ;
266+ }
267+
268+ cfg. files ( sqlean_sources) ;
269+
270+ let sqlean = Path :: new ( BUNDLED_DIR )
271+ . join ( "src" )
272+ . join ( "sqlite3-sqlean-generated.c" ) ;
273+ generate_sqlean ( & enabled_extensions, & sqlean) . unwrap ( ) ;
274+ cfg. file ( & sqlean) ;
275+
276+ cfg. include ( format ! ( "{BUNDLED_DIR}/sqlean/" ) ) ;
277+ }
278+
172279 if cfg ! ( feature = "wasmtime-bindings" ) {
173280 cfg. flag ( "-DLIBSQL_ENABLE_WASM_RUNTIME=1" ) ;
174281 }
0 commit comments