blob: 0e1d0fcd1abcd01a4f662b60a6beff0586b1539c [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\""}
183 }
184 } elseif {![info exists seen_hdr($hdr)]} {
mistachkin8de12502015-03-24 21:52:12 +0000185 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
186 set seen_hdr($hdr) 1
187 }
188 puts $out $line
189 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
190 # This include file must be kept because there was a "keep"
191 # directive inside of a line comment.
drh168f9f52011-09-17 17:29:20 +0000192 puts $out $line
193 } else {
mistachkin8de12502015-03-24 21:52:12 +0000194 # Comment out the entire line, replacing any nested comment
195 # begin/end markers with the harmless substring "**".
196 puts $out "/* [string map [list /* ** */ **] $line] */"
drh168f9f52011-09-17 17:29:20 +0000197 }
198 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
199 puts $out "#if 0"
200 } elseif {!$linemacros && [regexp {^#line} $line]} {
201 # Skip #line directives.
202 } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000203 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
204 # functions if this header file does not need it.
205 if {![info exists varonly_hdr($tail)]
206 && [regexp $declpattern $line all rettype funcname rest]} {
207 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000208 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
209 # so that linkage can be modified at compile-time.
210 if {[regexp {^sqlite3_} $funcname]} {
mistachkin8de12502015-03-24 21:52:12 +0000211 set line SQLITE_API
212 append line " " [string trim $rettype]
213 if {[string index $rettype end] ne "*"} {
214 append line " "
215 }
216 if {[lsearch -exact $cdecllist $funcname] >= 0} {
217 append line SQLITE_CDECL
218 } else {
219 append line SQLITE_STDCALL
220 }
221 append line " " $funcname $rest
222 puts $out $line
drh168f9f52011-09-17 17:29:20 +0000223 } else {
224 puts $out "SQLITE_PRIVATE $line"
225 }
226 } elseif {[regexp $varpattern $line all varname]} {
mistachkin8de12502015-03-24 21:52:12 +0000227 # Add the SQLITE_PRIVATE before variable declarations or
228 # definitions for internal use
229 regsub {^SQLITE_API } $line {} line
230 if {![regexp {^sqlite3_} $varname]} {
231 regsub {^extern } $line {} line
232 puts $out "SQLITE_PRIVATE $line"
233 } else {
234 if {[regexp {const char sqlite3_version\[\];} $line]} {
235 set line {const char sqlite3_version[] = SQLITE_VERSION;}
236 }
237 regsub {^SQLITE_EXTERN } $line {} line
238 puts $out "SQLITE_API $line"
drh168f9f52011-09-17 17:29:20 +0000239 }
drh168f9f52011-09-17 17:29:20 +0000240 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000241 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000242 regsub {^SQLITE_EXTERN } $line {} line
mistachkin8de12502015-03-24 21:52:12 +0000243 puts $out $line
drh168f9f52011-09-17 17:29:20 +0000244 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
mistachkin8de12502015-03-24 21:52:12 +0000245 regsub {^SQLITE_API } $line {} line
drh168f9f52011-09-17 17:29:20 +0000246 puts $out "SQLITE_PRIVATE $line"
247 } else {
248 puts $out $line
249 }
250 } else {
251 puts $out $line
252 }
253 }
254 close $in
255 section_comment "End of $tail"
256}
257
258
259# Process the source files. Process files containing commonly
260# used subroutines first in order to help the compiler find
261# inlining opportunities.
262#
263foreach file {
264 sqliteInt.h
265
266 global.c
267 ctime.c
268 status.c
269 date.c
270 os.c
271
272 fault.c
273 mem0.c
274 mem1.c
275 mem2.c
276 mem3.c
277 mem5.c
278 mutex.c
279 mutex_noop.c
drh168f9f52011-09-17 17:29:20 +0000280 mutex_unix.c
281 mutex_w32.c
282 malloc.c
283 printf.c
284 random.c
drhf51446a2012-07-21 19:40:42 +0000285 threads.c
drh168f9f52011-09-17 17:29:20 +0000286 utf.c
287 util.c
288 hash.c
289 opcodes.c
290
drh168f9f52011-09-17 17:29:20 +0000291 os_unix.c
292 os_win.c
293
294 bitvec.c
295 pcache.c
296 pcache1.c
297 rowset.c
298 pager.c
299 wal.c
300
301 btmutex.c
302 btree.c
303 backup.c
304
305 vdbemem.c
306 vdbeaux.c
307 vdbeapi.c
308 vdbetrace.c
309 vdbe.c
310 vdbeblob.c
311 vdbesort.c
312 journal.c
313 memjournal.c
314
315 walker.c
316 resolve.c
317 expr.c
318 alter.c
319 analyze.c
320 attach.c
321 auth.c
322 build.c
323 callback.c
324 delete.c
325 func.c
326 fkey.c
327 insert.c
328 legacy.c
329 loadext.c
330 pragma.c
331 prepare.c
332 select.c
333 table.c
334 trigger.c
335 update.c
336 vacuum.c
337 vtab.c
338 where.c
339
340 parse.c
341
342 tokenize.c
343 complete.c
344
345 main.c
346 notify.c
347} {
348 copy_file tsrc/$file
349}
350
351close $out