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 --srcdir $SRC 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 version number is needed to generate the header 27# comment of the amalgamation. 28# 29set addstatic 1 30set linemacros 0 31set useapicall 0 32for {set i 0} {$i<[llength $argv]} {incr i} { 33 set x [lindex $argv $i] 34 if {[regexp {^-+nostatic$} $x]} { 35 set addstatic 0 36 } elseif {[regexp {^-+linemacros} $x]} { 37 set linemacros 1 38 } elseif {[regexp {^-+useapicall} $x]} { 39 set useapicall 1 40 } else { 41 error "unknown command-line option: $x" 42 } 43} 44set in [open tsrc/sqlite3.h] 45set cnt 0 46set VERSION ????? 47while {![eof $in]} { 48 set line [gets $in] 49 if {$line=="" && [eof $in]} break 50 incr cnt 51 regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION 52} 53close $in 54 55# Open the output file and write a header comment at the beginning 56# of the file. 57# 58set out [open sqlite3.c w] 59# Force the output to use unix line endings, even on Windows. 60fconfigure $out -translation lf 61set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] 62puts $out [subst \ 63{/****************************************************************************** 64** This file is an amalgamation of many separate C source files from SQLite 65** version $VERSION. By combining all the individual C code files into this 66** single large file, the entire code can be compiled as a single translation 67** unit. This allows many compilers to do optimizations that would not be 68** possible if the files were compiled separately. Performance improvements 69** of 5% or more are commonly seen when SQLite is compiled as a single 70** translation unit. 71** 72** This file is all you need to compile SQLite. To use SQLite in other 73** programs, you need this file and the "sqlite3.h" header file that defines 74** the programming interface to the SQLite library. (If you do not have 75** the "sqlite3.h" header file at hand, you will find a copy embedded within 76** the text of this file. Search for "Begin file sqlite3.h" to find the start 77** of the embedded sqlite3.h header file.) Additional code files may be needed 78** if you want a wrapper to interface SQLite with your choice of programming 79** language. The code for the "sqlite3" command-line shell is also in a 80** separate file. This file contains only code for the core SQLite library. 81*/ 82#define SQLITE_CORE 1 83#define SQLITE_AMALGAMATION 1}] 84if {$addstatic} { 85 puts $out \ 86{#ifndef SQLITE_PRIVATE 87# define SQLITE_PRIVATE static 88#endif} 89} 90 91# These are the header files used by SQLite. The first time any of these 92# files are seen in a #include statement in the C code, include the complete 93# text of the file in-line. The file only needs to be included once. 94# 95foreach hdr { 96 btree.h 97 btreeInt.h 98 fts3.h 99 fts3Int.h 100 fts3_hash.h 101 fts3_tokenizer.h 102 hash.h 103 hwtime.h 104 keywordhash.h 105 msvc.h 106 mutex.h 107 opcodes.h 108 os_common.h 109 os_setup.h 110 os_win.h 111 os.h 112 pager.h 113 parse.h 114 pcache.h 115 pragma.h 116 rtree.h 117 sqlite3session.h 118 sqlite3.h 119 sqlite3ext.h 120 sqlite3rbu.h 121 sqliteicu.h 122 sqliteInt.h 123 sqliteLimit.h 124 vdbe.h 125 vdbeInt.h 126 vxworks.h 127 wal.h 128 whereInt.h 129} { 130 set available_hdr($hdr) 1 131} 132set available_hdr(sqliteInt.h) 0 133set available_hdr(sqlite3session.h) 0 134 135# These headers should be copied into the amalgamation without modifying any 136# of their function declarations or definitions. 137set varonly_hdr(sqlite3.h) 1 138 139# These are the functions that accept a variable number of arguments. They 140# always need to use the "cdecl" calling convention even when another calling 141# convention (e.g. "stcall") is being used for the rest of the library. 142set cdecllist { 143 sqlite3_config 144 sqlite3_db_config 145 sqlite3_log 146 sqlite3_mprintf 147 sqlite3_snprintf 148 sqlite3_test_control 149 sqlite3_vtab_config 150} 151 152# 78 stars used for comment formatting. 153set s78 \ 154{*****************************************************************************} 155 156# Insert a comment into the code 157# 158proc section_comment {text} { 159 global out s78 160 set n [string length $text] 161 set nstar [expr {60 - $n}] 162 set stars [string range $s78 0 $nstar] 163 puts $out "/************** $text $stars/" 164} 165 166# Read the source file named $filename and write it into the 167# sqlite3.c output file. If any #include statements are seen, 168# process them appropriately. 169# 170proc copy_file {filename} { 171 global seen_hdr available_hdr varonly_hdr cdecllist out 172 global addstatic linemacros useapicall 173 set ln 0 174 set tail [file tail $filename] 175 section_comment "Begin file $tail" 176 if {$linemacros} {puts $out "#line 1 \"$filename\""} 177 set in [open $filename r] 178 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)} 179 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)} 180 if {[file extension $filename]==".h"} { 181 set declpattern " *$declpattern" 182 } 183 set declpattern ^$declpattern\$ 184 while {![eof $in]} { 185 set line [gets $in] 186 incr ln 187 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { 188 if {[info exists available_hdr($hdr)]} { 189 if {$available_hdr($hdr)} { 190 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} { 191 set available_hdr($hdr) 0 192 } 193 section_comment "Include $hdr in the middle of $tail" 194 copy_file tsrc/$hdr 195 section_comment "Continuing where we left off in $tail" 196 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""} 197 } else { 198 # Comment out the entire line, replacing any nested comment 199 # begin/end markers with the harmless substring "**". 200 puts $out "/* [string map [list /* ** */ **] $line] */" 201 } 202 } elseif {![info exists seen_hdr($hdr)]} { 203 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} { 204 set seen_hdr($hdr) 1 205 } 206 puts $out $line 207 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} { 208 # This include file must be kept because there was a "keep" 209 # directive inside of a line comment. 210 puts $out $line 211 } else { 212 # Comment out the entire line, replacing any nested comment 213 # begin/end markers with the harmless substring "**". 214 puts $out "/* [string map [list /* ** */ **] $line] */" 215 } 216 } elseif {[regexp {^#ifdef __cplusplus} $line]} { 217 puts $out "#if 0" 218 } elseif {!$linemacros && [regexp {^#line} $line]} { 219 # Skip #line directives. 220 } elseif {$addstatic 221 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} { 222 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before 223 # functions if this header file does not need it. 224 if {![info exists varonly_hdr($tail)] 225 && [regexp $declpattern $line all rettype funcname rest]} { 226 regsub {^SQLITE_API } $line {} line 227 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. 228 # so that linkage can be modified at compile-time. 229 if {[regexp {^sqlite3[a-z]*_} $funcname]} { 230 set line SQLITE_API 231 append line " " [string trim $rettype] 232 if {[string index $rettype end] ne "*"} { 233 append line " " 234 } 235 if {$useapicall} { 236 if {[lsearch -exact $cdecllist $funcname] >= 0} { 237 append line SQLITE_CDECL " " 238 } else { 239 append line SQLITE_APICALL " " 240 } 241 } 242 append line $funcname $rest 243 puts $out $line 244 } else { 245 puts $out "SQLITE_PRIVATE $line" 246 } 247 } elseif {[regexp $varpattern $line all varname]} { 248 # Add the SQLITE_PRIVATE before variable declarations or 249 # definitions for internal use 250 regsub {^SQLITE_API } $line {} line 251 if {![regexp {^sqlite3_} $varname]} { 252 regsub {^extern } $line {} line 253 puts $out "SQLITE_PRIVATE $line" 254 } else { 255 if {[regexp {const char sqlite3_version\[\];} $line]} { 256 set line {const char sqlite3_version[] = SQLITE_VERSION;} 257 } 258 regsub {^SQLITE_EXTERN } $line {} line 259 puts $out "SQLITE_API $line" 260 } 261 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} { 262 regsub {^SQLITE_API } $line {} line 263 regsub {^SQLITE_EXTERN } $line {} line 264 puts $out $line 265 } elseif {[regexp {^void \(\*sqlite3Os} $line]} { 266 regsub {^SQLITE_API } $line {} line 267 puts $out "SQLITE_PRIVATE $line" 268 } else { 269 puts $out $line 270 } 271 } else { 272 puts $out $line 273 } 274 } 275 close $in 276 section_comment "End of $tail" 277} 278 279 280# Process the source files. Process files containing commonly 281# used subroutines first in order to help the compiler find 282# inlining opportunities. 283# 284foreach file { 285 ctime.c 286 sqliteInt.h 287 288 global.c 289 status.c 290 date.c 291 os.c 292 293 fault.c 294 mem0.c 295 mem1.c 296 mem2.c 297 mem3.c 298 mem5.c 299 mutex.c 300 mutex_noop.c 301 mutex_unix.c 302 mutex_w32.c 303 malloc.c 304 printf.c 305 treeview.c 306 random.c 307 threads.c 308 utf.c 309 util.c 310 hash.c 311 opcodes.c 312 313 os_unix.c 314 os_win.c 315 316 bitvec.c 317 pcache.c 318 pcache1.c 319 rowset.c 320 pager.c 321 wal.c 322 323 btmutex.c 324 btree.c 325 backup.c 326 327 vdbemem.c 328 vdbeaux.c 329 vdbeapi.c 330 vdbetrace.c 331 vdbe.c 332 vdbeblob.c 333 vdbesort.c 334 memjournal.c 335 336 walker.c 337 resolve.c 338 expr.c 339 alter.c 340 analyze.c 341 attach.c 342 auth.c 343 build.c 344 callback.c 345 delete.c 346 func.c 347 fkey.c 348 insert.c 349 legacy.c 350 loadext.c 351 pragma.c 352 prepare.c 353 select.c 354 table.c 355 trigger.c 356 update.c 357 vacuum.c 358 vtab.c 359 wherecode.c 360 whereexpr.c 361 where.c 362 363 parse.c 364 365 tokenize.c 366 complete.c 367 368 main.c 369 notify.c 370 371 fts3.c 372 fts3_aux.c 373 fts3_expr.c 374 fts3_hash.c 375 fts3_porter.c 376 fts3_tokenizer.c 377 fts3_tokenizer1.c 378 fts3_tokenize_vtab.c 379 fts3_write.c 380 fts3_snippet.c 381 fts3_unicode.c 382 fts3_unicode2.c 383 384 rtree.c 385 icu.c 386 fts3_icu.c 387 sqlite3rbu.c 388 dbstat.c 389 sqlite3session.c 390 json1.c 391 fts5.c 392 stmts.c 393} { 394 copy_file tsrc/$file 395} 396 397close $out 398