blob: 601b8cce8c3e6d85d88c285c39909fb787c56e2d [file] [log] [blame]
drh168f9f52011-09-17 17:29:20 +00001#!/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#
mistachkin26bbfaa2015-03-24 21:34:53 +000020# tclsh mksqlite3c-noext.tcl
drh168f9f52011-09-17 17:29:20 +000021#
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
mistachkin26bbfaa2015-03-24 21:34:53 +000026# from in this file. The version number is needed to generate the header
drh168f9f52011-09-17 17:29:20 +000027# comment of the amalgamation.
28#
29if {[lsearch $argv --nostatic]>=0} {
30 set addstatic 0
31} else {
32 set addstatic 1
33}
34if {[lsearch $argv --linemacros]>=0} {
35 set linemacros 1
36} else {
37 set linemacros 0
38}
39set in [open tsrc/sqlite3.h]
40set cnt 0
41set VERSION ?????
42while {![eof $in]} {
43 set line [gets $in]
44 if {$line=="" && [eof $in]} break
45 incr cnt
46 regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
47}
48close $in
49
50# Open the output file and write a header comment at the beginning
51# of the file.
52#
53set out [open sqlite3.c w]
54# Force the output to use unix line endings, even on Windows.
55fconfigure $out -translation lf
56set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
57puts $out [subst \
58{/******************************************************************************
59** This file is an amalgamation of many separate C source files from SQLite
60** version $VERSION. By combining all the individual C code files into this
61** single large file, the entire code can be compiled as a single translation
62** unit. This allows many compilers to do optimizations that would not be
63** possible if the files were compiled separately. Performance improvements
64** of 5% or more are commonly seen when SQLite is compiled as a single
65** translation unit.
66**
67** This file is all you need to compile SQLite. To use SQLite in other
68** programs, you need this file and the "sqlite3.h" header file that defines
69** the programming interface to the SQLite library. (If you do not have
70** the "sqlite3.h" header file at hand, you will find a copy embedded within
71** the text of this file. Search for "Begin file sqlite3.h" to find the start
72** of the embedded sqlite3.h header file.) Additional code files may be needed
73** if you want a wrapper to interface SQLite with your choice of programming
74** language. The code for the "sqlite3" command-line shell is also in a
75** separate file. This file contains only code for the core SQLite library.
76*/
77#define SQLITE_CORE 1
78#define SQLITE_AMALGAMATION 1}]
79if {$addstatic} {
80 puts $out \
81{#ifndef SQLITE_PRIVATE
82# define SQLITE_PRIVATE static
drh168f9f52011-09-17 17:29:20 +000083#endif}
84}
85
86# These are the header files used by SQLite. The first time any of these
87# files are seen in a #include statement in the C code, include the complete
88# text of the file in-line. The file only needs to be included once.
89#
90foreach hdr {
91 btree.h
92 btreeInt.h
93 hash.h
94 hwtime.h
95 keywordhash.h
mistachkin2318d332015-01-12 18:02:52 +000096 msvc.h
drh168f9f52011-09-17 17:29:20 +000097 mutex.h
98 opcodes.h
99 os_common.h
mistachkinf74b9e02013-11-26 01:00:31 +0000100 os_setup.h
mistachkin8bc52622013-11-25 09:36:07 +0000101 os_win.h
drh168f9f52011-09-17 17:29:20 +0000102 os.h
drh168f9f52011-09-17 17:29:20 +0000103 pager.h
104 parse.h
105 pcache.h
mistachkin8de12502015-03-24 21:52:12 +0000106 pragma.h
drh168f9f52011-09-17 17:29:20 +0000107 sqlite3ext.h
108 sqlite3.h
109 sqliteicu.h
110 sqliteInt.h
111 sqliteLimit.h
112 vdbe.h
113 vdbeInt.h
mistachkin8de12502015-03-24 21:52:12 +0000114 vxworks.h
drh168f9f52011-09-17 17:29:20 +0000115 wal.h
mistachkin8de12502015-03-24 21:52:12 +0000116 whereInt.h
drh168f9f52011-09-17 17:29:20 +0000117} {
118 set available_hdr($hdr) 1
119}
120set available_hdr(sqliteInt.h) 0
121
mistachkin8de12502015-03-24 21:52:12 +0000122# These headers should be copied into the amalgamation without modifying any
123# of their function declarations or definitions.
124set varonly_hdr(sqlite3.h) 1
125
126# These are the functions that accept a variable number of arguments. They
127# always need to use the "cdecl" calling convention even when another calling
128# convention (e.g. "stcall") is being used for the rest of the library.
129set cdecllist {
130 sqlite3_config
131 sqlite3_db_config
132 sqlite3_log
133 sqlite3_mprintf
134 sqlite3_snprintf
135 sqlite3_test_control
136 sqlite3_vtab_config
137}
138
drh168f9f52011-09-17 17:29:20 +0000139# 78 stars used for comment formatting.
140set s78 \
141{*****************************************************************************}
142
143# Insert a comment into the code
144#
145proc section_comment {text} {
146 global out s78
147 set n [string length $text]
148 set nstar [expr {60 - $n}]
149 set stars [string range $s78 0 $nstar]
150 puts $out "/************** $text $stars/"
151}
152
153# Read the source file named $filename and write it into the
154# sqlite3.c output file. If any #include statements are seen,
mistachkin8de12502015-03-24 21:52:12 +0000155# process them appropriately.
drh168f9f52011-09-17 17:29:20 +0000156#
157proc copy_file {filename} {
mistachkin8de12502015-03-24 21:52:12 +0000158 global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
drh168f9f52011-09-17 17:29:20 +0000159 set ln 0
160 set tail [file tail $filename]
161 section_comment "Begin file $tail"
162 if {$linemacros} {puts $out "#line 1 \"$filename\""}
163 set in [open $filename r]
164 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
mistachkin8de12502015-03-24 21:52:12 +0000165 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
drh168f9f52011-09-17 17:29:20 +0000166 if {[file extension $filename]==".h"} {
167 set declpattern " *$declpattern"
168 }
mistachkin8de12502015-03-24 21:52:12 +0000169 set declpattern ^$declpattern\$
drh168f9f52011-09-17 17:29:20 +0000170 while {![eof $in]} {
171 set line [gets $in]
172 incr ln
173 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
174 if {[info exists available_hdr($hdr)]} {
175 if {$available_hdr($hdr)} {
176 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
177 set available_hdr($hdr) 0
178 }
179 section_comment "Include $hdr in the middle of $tail"
180 copy_file tsrc/$hdr
181 section_comment "Continuing where we left off in $tail"
182 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
mistachkin3a2a6862015-07-15 21:00:33 +0000183 } else {
184 # Comment out the entire line, replacing any nested comment
185 # begin/end markers with the harmless substring "**".
186 puts $out "/* [string map [list /* ** */ **] $line] */"
drh168f9f52011-09-17 17:29:20 +0000187 }
188 } elseif {![info exists seen_hdr($hdr)]} {
mistachkin8de12502015-03-24 21:52:12 +0000189 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
190 set seen_hdr($hdr) 1
191 }
192 puts $out $line
193 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
194 # This include file must be kept because there was a "keep"
195 # directive inside of a line comment.
drh168f9f52011-09-17 17:29:20 +0000196 puts $out $line
197 } else {
mistachkin8de12502015-03-24 21:52:12 +0000198 # Comment out the entire line, replacing any nested comment
199 # begin/end markers with the harmless substring "**".
200 puts $out "/* [string map [list /* ** */ **] $line] */"
drh168f9f52011-09-17 17:29:20 +0000201 }
202 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
203 puts $out "#if 0"
204 } elseif {!$linemacros && [regexp {^#line} $line]} {
205 # Skip #line directives.
206 } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000207 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
208 # functions if this header file does not need it.
209 if {![info exists varonly_hdr($tail)]
210 && [regexp $declpattern $line all rettype funcname rest]} {
211 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000212 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
213 # so that linkage can be modified at compile-time.
214 if {[regexp {^sqlite3_} $funcname]} {
mistachkin8de12502015-03-24 21:52:12 +0000215 set line SQLITE_API
216 append line " " [string trim $rettype]
217 if {[string index $rettype end] ne "*"} {
218 append line " "
219 }
220 if {[lsearch -exact $cdecllist $funcname] >= 0} {
221 append line SQLITE_CDECL
222 } else {
223 append line SQLITE_STDCALL
224 }
225 append line " " $funcname $rest
226 puts $out $line
drh168f9f52011-09-17 17:29:20 +0000227 } else {
228 puts $out "SQLITE_PRIVATE $line"
229 }
230 } elseif {[regexp $varpattern $line all varname]} {
mistachkin8de12502015-03-24 21:52:12 +0000231 # Add the SQLITE_PRIVATE before variable declarations or
232 # definitions for internal use
233 regsub {^SQLITE_API } $line {} line
234 if {![regexp {^sqlite3_} $varname]} {
235 regsub {^extern } $line {} line
236 puts $out "SQLITE_PRIVATE $line"
237 } else {
238 if {[regexp {const char sqlite3_version\[\];} $line]} {
239 set line {const char sqlite3_version[] = SQLITE_VERSION;}
240 }
241 regsub {^SQLITE_EXTERN } $line {} line
242 puts $out "SQLITE_API $line"
drh168f9f52011-09-17 17:29:20 +0000243 }
drh168f9f52011-09-17 17:29:20 +0000244 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000245 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000246 regsub {^SQLITE_EXTERN } $line {} line
mistachkin8de12502015-03-24 21:52:12 +0000247 puts $out $line
drh168f9f52011-09-17 17:29:20 +0000248 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000249 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000250 puts $out "SQLITE_PRIVATE $line"
251 } else {
252 puts $out $line
253 }
254 } else {
255 puts $out $line
256 }
257 }
258 close $in
259 section_comment "End of $tail"
260}
261
262
263# Process the source files. Process files containing commonly
264# used subroutines first in order to help the compiler find
265# inlining opportunities.
266#
267foreach file {
268 sqliteInt.h
269
270 global.c
271 ctime.c
272 status.c
273 date.c
274 os.c
275
276 fault.c
277 mem0.c
278 mem1.c
279 mem2.c
280 mem3.c
281 mem5.c
282 mutex.c
283 mutex_noop.c
drh168f9f52011-09-17 17:29:20 +0000284 mutex_unix.c
285 mutex_w32.c
286 malloc.c
287 printf.c
288 random.c
drhf51446a2012-07-21 19:40:42 +0000289 threads.c
drh168f9f52011-09-17 17:29:20 +0000290 utf.c
291 util.c
292 hash.c
293 opcodes.c
294
drh168f9f52011-09-17 17:29:20 +0000295 os_unix.c
296 os_win.c
297
298 bitvec.c
299 pcache.c
300 pcache1.c
301 rowset.c
302 pager.c
303 wal.c
304
305 btmutex.c
306 btree.c
307 backup.c
308
309 vdbemem.c
310 vdbeaux.c
311 vdbeapi.c
312 vdbetrace.c
313 vdbe.c
314 vdbeblob.c
315 vdbesort.c
316 journal.c
317 memjournal.c
318
319 walker.c
320 resolve.c
321 expr.c
322 alter.c
323 analyze.c
324 attach.c
325 auth.c
326 build.c
327 callback.c
328 delete.c
329 func.c
330 fkey.c
331 insert.c
332 legacy.c
333 loadext.c
334 pragma.c
335 prepare.c
336 select.c
337 table.c
338 trigger.c
339 update.c
340 vacuum.c
341 vtab.c
342 where.c
343
344 parse.c
345
346 tokenize.c
347 complete.c
348
349 main.c
350 notify.c
351} {
352 copy_file tsrc/$file
353}
354
355close $out