1- //! Compiles SQLite3MC and SQLCipher into one binary, prefixing each object's globals apart .
1+ //! Compiles the vendored amalgamation as a plain static library .
22
3- use std:: {
4- env,
5- fmt:: Write as _,
6- fs,
7- path:: { Path , PathBuf } ,
8- process:: Command ,
9- } ;
10-
11- struct Side < ' a > {
12- prefix : & ' a str ,
13- source : PathBuf ,
14- includes : & ' a [ & ' a Path ] ,
15- defines : & ' a [ ( & ' a str , Option < & ' a str > ) ] ,
16- }
3+ use std:: { env, fs, path:: PathBuf , process:: Command } ;
174
185fn main ( ) {
196 assert_eq ! (
207 env:: var( "CARGO_CFG_TARGET_OS" ) . as_deref( ) ,
218 Ok ( "linux" ) ,
22- "the symbol renaming needs ELF objects and GNU-compatible nm and objcopy, so the fuzz crate builds on Linux only"
9+ "the fuzz crate builds on Linux only"
2310 ) ;
2411 let out = PathBuf :: from ( env:: var_os ( "OUT_DIR" ) . expect ( "cargo sets OUT_DIR" ) ) ;
2512 let mc_dir = sqlite3mc_src:: source_dir ( ) ;
26- let sc_dir = sqlcipher_src:: source_dir ( ) ;
27- let common = [
13+ let mut cc = cc:: Build :: new ( ) ;
14+ cc. file ( mc_dir. join ( sqlite3mc_src:: SOURCE_FILE ) )
15+ . warnings ( false ) ;
16+ cc. include ( mc_dir) ;
17+ for ( name, value) in [
18+ ( "SQLITE_CORE" , None ) ,
2819 ( "SQLITE_TEMP_STORE" , Some ( "2" ) ) ,
2920 ( "SQLITE_ENABLE_DBPAGE_VTAB" , None ) ,
3021 ( "SQLITE_DEFAULT_MEMSTATUS" , Some ( "0" ) ) ,
31- ] ;
32- let mc_defines = [ common. as_slice ( ) , & [ ( "SQLITE_CORE" , None ) ] ] . concat ( ) ;
33- build (
34- & Side {
35- prefix : "mc" ,
36- source : mc_dir. join ( sqlite3mc_src:: SOURCE_FILE ) ,
37- includes : & [ mc_dir] ,
38- defines : & mc_defines,
39- } ,
40- & out,
41- ) ;
42- let crate_dir = Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
43- build (
44- & Side {
45- prefix : "sc" ,
46- source : sqlcipher_unit ( crate_dir, sc_dir, & out) ,
47- includes : & [
48- sc_dir,
49- & sc_dir. join ( sqlcipher_src:: LIBTOMCRYPT_INCLUDE_DIR ) ,
50- crate_dir,
51- ] ,
52- defines : & common,
53- } ,
54- & out,
55- ) ;
56- println ! ( "cargo:rustc-link-search=native={}" , out. display( ) ) ;
57- for lib in [ "m" , "pthread" , "dl" ] {
58- println ! ( "cargo:rustc-link-lib={lib}" ) ;
59- }
60- println ! ( "cargo:rerun-if-changed=build.rs" ) ;
61- for file in [
62- "sqlcipher-wrapper.c" ,
63- "sqlcipher-ltc.h" ,
64- "sqlcipher-entropy.c" ,
6522 ] {
66- println ! ( "cargo:rerun-if-changed={file}" ) ;
67- }
68- println ! ( "cargo:rerun-if-env-changed=NM" ) ;
69- println ! ( "cargo:rerun-if-env-changed=OBJCOPY" ) ;
70- }
71-
72- fn build ( side : & Side < ' _ > , out : & Path ) {
73- let mut cc = cc:: Build :: new ( ) ;
74- cc. file ( & side. source ) . warnings ( false ) ;
75- for include in side. includes {
76- println ! ( "cargo:rerun-if-changed={}" , include. display( ) ) ;
77- cc. include ( include) ;
78- }
79- for ( name, value) in side. defines {
80- cc. define ( name, * value) ;
23+ cc. define ( name, value) ;
8124 }
8225 instrument ( & mut cc) ;
8326 let objects = cc. compile_intermediates ( ) ;
8427 let [ object] = objects. as_slice ( ) else {
85- panic ! (
86- "{} compiled to {} objects" ,
87- side. source. display( ) ,
88- objects. len( )
89- ) ;
28+ panic ! ( "the amalgamation compiled to {} objects" , objects. len( ) ) ;
9029 } ;
91-
92- let map = out. join ( format ! ( "{}.redefine" , side. prefix) ) ;
93- fs:: write ( & map, redefinitions ( object, side. prefix ) ) . expect ( "OUT_DIR is writable" ) ;
94- let renamed = out. join ( format ! ( "{}.o" , side. prefix) ) ;
95- run ( Command :: new ( tool ( "OBJCOPY" , "objcopy" ) )
96- . arg ( format ! ( "--redefine-syms={}" , map. display( ) ) )
97- . arg ( object)
98- . arg ( & renamed) ) ;
99-
100- let archive = out. join ( format ! ( "lib{}.a" , side. prefix) ) ;
30+ let archive = out. join ( "libmc.a" ) ;
10131 let _ = fs:: remove_file ( & archive) ;
102- run ( cc. get_archiver ( ) . arg ( "crs" ) . arg ( & archive) . arg ( & renamed) ) ;
103- println ! ( "cargo:rustc-link-lib=static={}" , side. prefix) ;
104- }
105-
106- /// Writes the one translation unit SQLCipher builds from, the wrapper's configuration and SQLCipher, then every
107- /// libtomcrypt source in order, then the entropy hook, all sharing one configuration as upstream's single-file
108- /// libtomcrypt does.
109- fn sqlcipher_unit ( crate_dir : & Path , sc_dir : & Path , out : & Path ) -> PathBuf {
110- let sources = std:: iter:: once ( crate_dir. join ( "sqlcipher-wrapper.c" ) )
111- . chain (
112- sqlcipher_src:: LIBTOMCRYPT_SOURCES
113- . iter ( )
114- . map ( |source| sc_dir. join ( source) ) ,
115- )
116- . chain ( std:: iter:: once ( crate_dir. join ( "sqlcipher-entropy.c" ) ) ) ;
117- let unit = sources. fold ( String :: new ( ) , |mut unit, source| {
118- let _ = writeln ! ( unit, "#include \" {}\" " , source. display( ) ) ;
119- unit
120- } ) ;
121- let path = out. join ( "sqlcipher-unit.c" ) ;
122- fs:: write ( & path, unit) . expect ( "OUT_DIR is writable" ) ;
123- path
32+ run ( cc. get_archiver ( ) . arg ( "crs" ) . arg ( & archive) . arg ( object) ) ;
33+ println ! ( "cargo:rustc-link-search=native={}" , out. display( ) ) ;
34+ println ! ( "cargo:rustc-link-lib=static=mc" ) ;
35+ for lib in [ "m" , "pthread" , "dl" ] {
36+ println ! ( "cargo:rustc-link-lib={lib}" ) ;
37+ }
38+ println ! ( "cargo:rerun-if-changed=build.rs" ) ;
12439}
12540
12641/// Gives the C side the coverage and sanitizer instrumentation `cargo fuzz` gives the Rust side.
@@ -139,25 +54,7 @@ fn instrument(cc: &mut cc::Build) {
13954 }
14055}
14156
142- /// One `old new` line per global symbol the object defines.
143- fn redefinitions ( object : & Path , prefix : & str ) -> String {
144- let listing = run ( Command :: new ( tool ( "NM" , "nm" ) )
145- . args ( [ "--defined-only" , "--extern-only" , "--format=posix" ] )
146- . arg ( object) ) ;
147- listing
148- . lines ( )
149- . filter_map ( |line| line. split_whitespace ( ) . next ( ) )
150- . fold ( String :: new ( ) , |mut map, name| {
151- let _ = writeln ! ( map, "{name} {prefix}_{name}" ) ;
152- map
153- } )
154- }
155-
156- fn tool ( var : & str , default : & str ) -> String {
157- env:: var ( var) . unwrap_or_else ( |_| default. to_owned ( ) )
158- }
159-
160- fn run ( command : & mut Command ) -> String {
57+ fn run ( command : & mut Command ) {
16158 let output = command
16259 . output ( )
16360 . unwrap_or_else ( |e| panic ! ( "cannot run {command:?}: {e}" ) ) ;
@@ -166,5 +63,4 @@ fn run(command: &mut Command) -> String {
16663 "{command:?} failed: {}" ,
16764 String :: from_utf8_lossy( & output. stderr)
16865 ) ;
169- String :: from_utf8 ( output. stdout ) . expect ( "tool output is UTF-8" )
17066}
0 commit comments