1 #!/usr/bin/tclsh 2 # 3 # To build a single huge source file holding all of SQLite (or at 4 # least the core components - the test harness, shell, and TCL 5 # interface are omitted.) first do 6 # 7 # make target_source 8 # 9 # The make target above moves all of the source code files into 10 # a subdirectory named "tsrc". (This script expects to find the files 11 # there and will not work if they are not found.) There are a few 12 # generated C code files that are also added to the tsrc directory. 13 # For example, the "parse.c" and "parse.h" files to implement the 14 # the parser are derived from "parse.y" using lemon. And the 15 # "keywordhash.h" files is generated by a program named "mkkeywordhash". 16 # 17 # After the "tsrc" directory has been created and populated, run 18 # this script: 19 # 20 # tclsh mksqlite3c.tcl 21 # 22 # The amalgamated SQLite code will be written into sqlite3.c 23 # 24 25 # Begin by reading the "sqlite3.h" header file. Extract the version number 26 # from in this file. The versioon number is needed to generate the header 27 # comment of the amalgamation. 28 # 29 if {[lsearch $argv --nostatic]>=0} { 30 set addstatic 0 31 } else { 32 set addstatic 1 33 } 34 set in [open tsrc/sqlite3.h] 35 set cnt 0 36 set VERSION ????? 37 while {![eof $in]} { 38 set line [gets $in] 39 if {$line=="" && [eof $in]} break 40 incr cnt 41 regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION 42 } 43 close $in 44 45 # Open the output file and write a header comment at the beginning 46 # of the file. 47 # 48 set out [open sqlite3.c w] 49 set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] 50 puts $out [subst \ 51 {/****************************************************************************** 52 ** This file is an amalgamation of many separate C source files from SQLite 53 ** version $VERSION. By combining all the individual C code files into this 54 ** single large file, the entire code can be compiled as a single translation 55 ** unit. This allows many compilers to do optimizations that would not be 56 ** possible if the files were compiled separately. Performance improvements 57 ** of 5% or more are commonly seen when SQLite is compiled as a single 58 ** translation unit. 59 ** 60 ** This file is all you need to compile SQLite. To use SQLite in other 61 ** programs, you need this file and the "sqlite3.h" header file that defines 62 ** the programming interface to the SQLite library. (If you do not have 63 ** the "sqlite3.h" header file at hand, you will find a copy embedded within 64 ** the text of this file. Search for "Begin file sqlite3.h" to find the start 65 ** of the embedded sqlite3.h header file.) Additional code files may be needed 66 ** if you want a wrapper to interface SQLite with your choice of programming 67 ** language. The code for the "sqlite3" command-line shell is also in a 68 ** separate file. This file contains only code for the core SQLite library. 69 */ 70 #define SQLITE_CORE 1 71 #define SQLITE_AMALGAMATION 1}] 72 if {$addstatic} { 73 puts $out \ 74 {#ifndef SQLITE_PRIVATE 75 # define SQLITE_PRIVATE static 76 #endif 77 #ifndef SQLITE_API 78 # define SQLITE_API 79 #endif} 80 } 81 82 # These are the header files used by SQLite. The first time any of these 83 # files are seen in a #include statement in the C code, include the complete 84 # text of the file in-line. The file only needs to be included once. 85 # 86 foreach hdr { 87 btree.h 88 btreeInt.h 89 fts3.h 90 fts3Int.h 91 fts3_hash.h 92 fts3_tokenizer.h 93 hash.h 94 hwtime.h 95 keywordhash.h 96 mutex.h 97 opcodes.h 98 os_common.h 99 os.h 100 os_os2.h 101 pager.h 102 parse.h 103 pcache.h 104 rtree.h 105 sqlite3ext.h 106 sqlite3.h 107 sqliteicu.h 108 sqliteInt.h 109 sqliteLimit.h 110 vdbe.h 111 vdbeInt.h 112 wal.h 113 } { 114 set available_hdr($hdr) 1 115 } 116 set available_hdr(sqliteInt.h) 0 117 118 # 78 stars used for comment formatting. 119 set s78 \ 120 {*****************************************************************************} 121 122 # Insert a comment into the code 123 # 124 proc section_comment {text} { 125 global out s78 126 set n [string length $text] 127 set nstar [expr {60 - $n}] 128 set stars [string range $s78 0 $nstar] 129 puts $out "/************** $text $stars/" 130 } 131 132 # Read the source file named $filename and write it into the 133 # sqlite3.c output file. If any #include statements are seen, 134 # process them approprately. 135 # 136 proc copy_file {filename} { 137 global seen_hdr available_hdr out addstatic 138 set tail [file tail $filename] 139 section_comment "Begin file $tail" 140 set in [open $filename r] 141 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)} 142 set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(} 143 if {[file extension $filename]==".h"} { 144 set declpattern " *$declpattern" 145 } 146 set declpattern ^$declpattern 147 while {![eof $in]} { 148 set line [gets $in] 149 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { 150 if {[info exists available_hdr($hdr)]} { 151 if {$available_hdr($hdr)} { 152 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} { 153 set available_hdr($hdr) 0 154 } 155 section_comment "Include $hdr in the middle of $tail" 156 copy_file tsrc/$hdr 157 section_comment "Continuing where we left off in $tail" 158 } 159 } elseif {![info exists seen_hdr($hdr)]} { 160 set seen_hdr($hdr) 1 161 puts $out $line 162 } 163 } elseif {[regexp {^#ifdef __cplusplus} $line]} { 164 puts $out "#if 0" 165 } elseif {[regexp {^#line} $line]} { 166 # Skip #line directives. 167 } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} { 168 regsub {^SQLITE_API } $line {} line 169 if {[regexp $declpattern $line all funcname]} { 170 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. 171 # so that linkage can be modified at compile-time. 172 if {[regexp {^sqlite3_} $funcname]} { 173 puts $out "SQLITE_API $line" 174 } else { 175 puts $out "SQLITE_PRIVATE $line" 176 } 177 } elseif {[regexp $varpattern $line all varname]} { 178 # Add the SQLITE_PRIVATE before variable declarations or 179 # definitions for internal use 180 if {![regexp {^sqlite3_} $varname]} { 181 regsub {^extern } $line {} line 182 puts $out "SQLITE_PRIVATE $line" 183 } else { 184 if {[regexp {const char sqlite3_version\[\];} $line]} { 185 set line {const char sqlite3_version[] = SQLITE_VERSION;} 186 } 187 regsub {^SQLITE_EXTERN } $line {} line 188 puts $out "SQLITE_API $line" 189 } 190 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} { 191 regsub {^SQLITE_EXTERN } $line {} line 192 puts $out "SQLITE_PRIVATE $line" 193 } elseif {[regexp {^void \(\*sqlite3Os} $line]} { 194 puts $out "SQLITE_PRIVATE $line" 195 } else { 196 puts $out $line 197 } 198 } else { 199 puts $out $line 200 } 201 } 202 close $in 203 section_comment "End of $tail" 204 } 205 206 207 # Process the source files. Process files containing commonly 208 # used subroutines first in order to help the compiler find 209 # inlining opportunities. 210 # 211 foreach file { 212 sqliteInt.h 213 214 global.c 215 ctime.c 216 status.c 217 date.c 218 os.c 219 220 fault.c 221 mem0.c 222 mem1.c 223 mem2.c 224 mem3.c 225 mem5.c 226 mutex.c 227 mutex_noop.c 228 mutex_os2.c 229 mutex_unix.c 230 mutex_w32.c 231 malloc.c 232 printf.c 233 random.c 234 utf.c 235 util.c 236 hash.c 237 opcodes.c 238 239 os_os2.c 240 os_unix.c 241 os_win.c 242 243 bitvec.c 244 pcache.c 245 pcache1.c 246 rowset.c 247 pager.c 248 wal.c 249 250 btmutex.c 251 btree.c 252 backup.c 253 254 vdbemem.c 255 vdbeaux.c 256 vdbeapi.c 257 vdbetrace.c 258 vdbe.c 259 vdbeblob.c 260 journal.c 261 memjournal.c 262 263 walker.c 264 resolve.c 265 expr.c 266 alter.c 267 analyze.c 268 attach.c 269 auth.c 270 build.c 271 callback.c 272 delete.c 273 func.c 274 fkey.c 275 insert.c 276 legacy.c 277 loadext.c 278 pragma.c 279 prepare.c 280 select.c 281 table.c 282 trigger.c 283 update.c 284 vacuum.c 285 vtab.c 286 where.c 287 288 parse.c 289 290 tokenize.c 291 complete.c 292 293 main.c 294 notify.c 295 296 recover.c 297 298 fts3.c 299 fts3_aux.c 300 fts3_expr.c 301 fts3_hash.c 302 fts3_porter.c 303 fts3_tokenizer.c 304 fts3_tokenizer1.c 305 fts3_write.c 306 fts3_snippet.c 307 308 rtree.c 309 icu.c 310 fts3_icu.c 311 } { 312 copy_file tsrc/$file 313 } 314 315 close $out 316