github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/generator.go (about)

     1  // Copyright 2017 The Sqlite Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build generator
     6  // +build generator
     7  
     8  package main
     9  
    10  import (
    11  	"archive/zip"
    12  	"bufio"
    13  	"fmt"
    14  	"io"
    15  	"io/ioutil"
    16  	"net/http"
    17  	"os"
    18  	"os/exec"
    19  	"path/filepath"
    20  	"runtime"
    21  	"strings"
    22  
    23  	"modernc.org/ccgo/v3/lib"
    24  )
    25  
    26  //	gcc
    27  //	-g
    28  //	-O2
    29  //	-DSQLITE_OS_UNIX=1
    30  //	-I.
    31  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src
    32  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/rtree
    33  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/icu
    34  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts3
    35  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/async
    36  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/session
    37  //	-I/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/userauth
    38  //	-D_HAVE_SQLITE_CONFIG_H
    39  //	-DBUILD_sqlite
    40  //	-DNDEBUG
    41  //	-I/usr/include/tcl8.6
    42  //	-DSQLITE_THREADSAFE=1
    43  //	-DSQLITE_HAVE_ZLIB=1
    44  //	-DSQLITE_NO_SYNC=1
    45  //	-DSQLITE_TEMP_STORE=1
    46  //	-DSQLITE_TEST=1
    47  //	-DSQLITE_CRASH_TEST=1
    48  //	-DTCLSH_INIT_PROC=sqlite3TestInit
    49  //	-DSQLITE_SERVER=1
    50  //	-DSQLITE_PRIVATE=
    51  //	-DSQLITE_CORE
    52  //	-DBUILD_sqlite
    53  //	-DSQLITE_SERIES_CONSTRAINT_VERIFY=1
    54  //	-DSQLITE_DEFAULT_PAGE_SIZE=1024
    55  //	-DSQLITE_ENABLE_STMTVTAB
    56  //	-DSQLITE_ENABLE_DBPAGE_VTAB
    57  //	-DSQLITE_ENABLE_BYTECODE_VTAB
    58  //	-DSQLITE_ENABLE_DESERIALIZE
    59  //	-o testfixture
    60  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test1.c
    61  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test2.c
    62  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test3.c
    63  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test4.c
    64  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test5.c
    65  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test6.c
    66  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test7.c
    67  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test8.c
    68  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test9.c
    69  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_autoext.c
    70  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_async.c
    71  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_backup.c
    72  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_bestindex.c
    73  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_blob.c
    74  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_btree.c
    75  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_config.c
    76  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_delete.c
    77  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_demovfs.c
    78  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_devsym.c
    79  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_fs.c
    80  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_func.c
    81  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_hexio.c
    82  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_init.c
    83  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_intarray.c
    84  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_journal.c
    85  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_malloc.c
    86  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_md5.c
    87  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_multiplex.c
    88  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_mutex.c
    89  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_onefile.c
    90  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_osinst.c
    91  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_pcache.c
    92  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_quota.c
    93  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_rtree.c
    94  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_schema.c
    95  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_server.c
    96  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_superlock.c
    97  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_syscall.c
    98  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_tclsh.c
    99  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_tclvar.c
   100  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_thread.c
   101  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_vdbecov.c
   102  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_vfs.c
   103  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_windirent.c
   104  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_window.c
   105  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/test_wsd.c
   106  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts3/fts3_term.c
   107  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts3/fts3_test.c
   108  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/session/test_session.c
   109  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/rbu/test_rbu.c
   110  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/expert/sqlite3expert.c
   111  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/expert/test_expert.c
   112  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/amatch.c
   113  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/carray.c
   114  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/closure.c
   115  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/csv.c
   116  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/decimal.c
   117  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/eval.c
   118  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/explain.c
   119  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/fileio.c
   120  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/fuzzer.c
   121  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts5/fts5_tcl.c
   122  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts5/fts5_test_mi.c
   123  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/fts5/fts5_test_tok.c
   124  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/ieee754.c
   125  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/mmapwarm.c
   126  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/nextchar.c
   127  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/normalize.c
   128  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/percentile.c
   129  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/prefixes.c
   130  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/regexp.c
   131  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/remember.c
   132  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/series.c
   133  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/spellfix.c
   134  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/totype.c
   135  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/unionvtab.c
   136  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/wholenumber.c
   137  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/misc/zipfile.c
   138  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/ext/userauth/userauth.c
   139  //	/home/jnml/src/modernc.org/sqlite/testdata/SQLite-3c5e63c2/src/tclsqlite.c
   140  //	sqlite3.c
   141  //	-L/usr/lib/x86_64-linux-gnu
   142  //	-ltcl8.6
   143  //	-ldl
   144  //	-lz
   145  //	-lpthread
   146  
   147  const (
   148  	volatiles = "-volatile=sqlite3_io_error_pending,sqlite3_open_file_count,sqlite3_pager_readdb_count,sqlite3_pager_writedb_count,sqlite3_pager_writej_count,sqlite3_search_count,sqlite3_sort_count,saved_cnt"
   149  )
   150  
   151  var (
   152  	configProduction = []string{
   153  		"-DHAVE_USLEEP",
   154  		"-DLONGDOUBLE_TYPE=double",
   155  		"-DSQLITE_CORE",
   156  		"-DSQLITE_ENABLE_COLUMN_METADATA",
   157  		"-DSQLITE_ENABLE_FTS5",
   158  		"-DSQLITE_ENABLE_GEOPOLY",
   159  		"-DSQLITE_ENABLE_JSON1",
   160  		"-DSQLITE_ENABLE_MEMORY_MANAGEMENT",
   161  		"-DSQLITE_ENABLE_OFFSET_SQL_FUNC",
   162  		"-DSQLITE_ENABLE_PREUPDATE_HOOK",
   163  		"-DSQLITE_ENABLE_RBU",
   164  		"-DSQLITE_ENABLE_RTREE",
   165  		"-DSQLITE_ENABLE_SESSION",
   166  		"-DSQLITE_ENABLE_SNAPSHOT",
   167  		"-DSQLITE_ENABLE_STAT4",
   168  		"-DSQLITE_ENABLE_UNLOCK_NOTIFY", // Adds sqlite3_unlock_notify().
   169  		"-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
   170  		"-DSQLITE_MUTEX_APPDEF=1",
   171  		"-DSQLITE_SOUNDEX",
   172  		"-DSQLITE_THREADSAFE=1",
   173  		//DONT "-DNDEBUG", // To enable GO_GENERATE=-DSQLITE_DEBUG
   174  		//DONT "-DSQLITE_DQS=0", // testfixture
   175  		//DONT "-DSQLITE_NO_SYNC=1",
   176  		//DONT "-DSQLITE_OMIT_DECLTYPE", // testfixture
   177  		//DONT "-DSQLITE_OMIT_DEPRECATED", // mptest
   178  		//DONT "-DSQLITE_OMIT_LOAD_EXTENSION", // mptest
   179  		//DONT "-DSQLITE_OMIT_SHARED_CACHE",
   180  		//DONT "-DSQLITE_USE_ALLOCA",
   181  		//TODO "-DHAVE_MALLOC_USABLE_SIZE"
   182  		//TODO "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", //TODO report bug
   183  		//TODO "-DSQLITE_ENABLE_FTS3",
   184  		//TODO "-DSQLITE_ENABLE_FTS3_PARENTHESIS",
   185  		//TODO "-DSQLITE_ENABLE_FTS3_TOKENIZER",
   186  		//TODO "-DSQLITE_ENABLE_FTS4",
   187  		//TODO "-DSQLITE_ENABLE_ICU",
   188  		//TODO "-DSQLITE_MAX_EXPR_DEPTH=0", // bug reported https://sqlite.org/forum/forumpost/87b9262f66, fixed in https://sqlite.org/src/info/5f58dd3a19605b6f
   189  		//TODO "-DSQLITE_MAX_MMAP_SIZE=8589934592", // testfixture, bug reported https://sqlite.org/forum/forumpost/34380589f7, fixed in https://sqlite.org/src/info/d8e47382160e98be
   190  		//TODO- "-DSQLITE_DEBUG",
   191  		//TODO- "-DSQLITE_ENABLE_API_ARMOR",
   192  		//TODO- "-DSQLITE_MEMDEBUG",
   193  	}
   194  
   195  	configTest = []string{
   196  		"-DHAVE_USLEEP",
   197  		"-DLONGDOUBLE_TYPE=double",
   198  		"-DSQLITE_CKSUMVFS_STATIC",
   199  		"-DSQLITE_CORE",                   // testfixture
   200  		"-DSQLITE_DEFAULT_MEMSTATUS=0",    // bug reported https://sqlite.org/forum/info/d8dfd4771689be35, fixed in https://sqlite.org/src/info/3c5e63c22ffbfeb6
   201  		"-DSQLITE_DEFAULT_PAGE_SIZE=1024", // testfixture, hardcoded. See file_pages in autovacuum.test.
   202  		"-DSQLITE_ENABLE_BYTECODE_VTAB",   // testfixture
   203  		"-DSQLITE_ENABLE_COLUMN_METADATA",
   204  		"-DSQLITE_ENABLE_DBPAGE_VTAB", // testfixture
   205  		"-DSQLITE_ENABLE_DBSTAT_VTAB",
   206  		"-DSQLITE_ENABLE_DESERIALIZE", // testfixture
   207  		"-DSQLITE_ENABLE_EXPLAIN_COMMENTS",
   208  		"-DSQLITE_ENABLE_FTS5",
   209  		"-DSQLITE_ENABLE_GEOPOLY",
   210  		"-DSQLITE_ENABLE_JSON1",
   211  		"-DSQLITE_ENABLE_MEMORY_MANAGEMENT",
   212  		"-DSQLITE_ENABLE_OFFSET_SQL_FUNC",
   213  		"-DSQLITE_ENABLE_PREUPDATE_HOOK",
   214  		"-DSQLITE_ENABLE_RBU",
   215  		"-DSQLITE_ENABLE_RTREE",
   216  		"-DSQLITE_ENABLE_SESSION",
   217  		"-DSQLITE_ENABLE_SNAPSHOT",
   218  		"-DSQLITE_ENABLE_STAT4",
   219  		"-DSQLITE_ENABLE_STMTVTAB",      // testfixture
   220  		"-DSQLITE_ENABLE_UNLOCK_NOTIFY", // Adds sqlite3_unlock_notify().
   221  		"-DSQLITE_HAVE_ZLIB=1",          // testfixture
   222  		"-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
   223  		"-DSQLITE_MUTEX_APPDEF=1",
   224  		"-DSQLITE_SOUNDEX",
   225  		"-DSQLITE_TEMP_STORE=1", // testfixture
   226  		"-DSQLITE_TEST",
   227  		"-DSQLITE_THREADSAFE=1",
   228  		//DONT "-DNDEBUG", // To enable GO_GENERATE=-DSQLITE_DEBUG
   229  		//DONT "-DSQLITE_DQS=0", // testfixture
   230  		//DONT "-DSQLITE_NO_SYNC=1",
   231  		//DONT "-DSQLITE_OMIT_DECLTYPE", // testfixture
   232  		//DONT "-DSQLITE_OMIT_DEPRECATED", // mptest
   233  		//DONT "-DSQLITE_OMIT_LOAD_EXTENSION", // mptest
   234  		//DONT "-DSQLITE_OMIT_SHARED_CACHE",
   235  		//DONT "-DSQLITE_USE_ALLOCA",
   236  		//TODO "-DHAVE_MALLOC_USABLE_SIZE"
   237  		//TODO "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", //TODO report bug
   238  		//TODO "-DSQLITE_ENABLE_FTS3",
   239  		//TODO "-DSQLITE_ENABLE_FTS3_PARENTHESIS",
   240  		//TODO "-DSQLITE_ENABLE_FTS3_TOKENIZER",
   241  		//TODO "-DSQLITE_ENABLE_FTS4",
   242  		//TODO "-DSQLITE_ENABLE_ICU",
   243  		//TODO "-DSQLITE_MAX_EXPR_DEPTH=0", // bug reported https://sqlite.org/forum/forumpost/87b9262f66, fixed in https://sqlite.org/src/info/5f58dd3a19605b6f
   244  		//TODO "-DSQLITE_MAX_MMAP_SIZE=8589934592", // testfixture, bug reported https://sqlite.org/forum/forumpost/34380589f7, fixed in https://sqlite.org/src/info/d8e47382160e98be
   245  		//TODO- "-DSQLITE_DEBUG",
   246  		//TODO- "-DSQLITE_ENABLE_API_ARMOR",
   247  		//TODO- "-DSQLITE_MEMDEBUG",
   248  	}
   249  
   250  	downloads = []struct {
   251  		dir, url string
   252  		sz       int
   253  		dev      bool
   254  	}{
   255  		{sqliteDir, "https://www.sqlite.org/2021/sqlite-amalgamation-3360000.zip", 2457, false},
   256  		{sqliteSrcDir, "https://www.sqlite.org/2021/sqlite-src-3360000.zip", 12814, false},
   257  	}
   258  
   259  	sqliteDir    = filepath.FromSlash("testdata/sqlite-amalgamation-3360000")
   260  	sqliteSrcDir = filepath.FromSlash("testdata/sqlite-src-3360000")
   261  )
   262  
   263  func download() {
   264  	tmp, err := ioutil.TempDir("", "")
   265  	if err != nil {
   266  		fmt.Fprintf(os.Stderr, "%s\n", err)
   267  		return
   268  	}
   269  
   270  	defer os.RemoveAll(tmp)
   271  
   272  	for _, v := range downloads {
   273  		dir := filepath.FromSlash(v.dir)
   274  		root := filepath.Dir(v.dir)
   275  		fi, err := os.Stat(dir)
   276  		switch {
   277  		case err == nil:
   278  			if !fi.IsDir() {
   279  				fmt.Fprintf(os.Stderr, "expected %s to be a directory\n", dir)
   280  			}
   281  			continue
   282  		default:
   283  			if !os.IsNotExist(err) {
   284  				fmt.Fprintf(os.Stderr, "%s", err)
   285  				continue
   286  			}
   287  		}
   288  
   289  		if err := func() error {
   290  			fmt.Printf("Downloading %v MB from %s\n", float64(v.sz)/1000, v.url)
   291  			resp, err := http.Get(v.url)
   292  			if err != nil {
   293  				return err
   294  			}
   295  
   296  			defer resp.Body.Close()
   297  
   298  			base := filepath.Base(v.url)
   299  			name := filepath.Join(tmp, base)
   300  			f, err := os.Create(name)
   301  			if err != nil {
   302  				return err
   303  			}
   304  
   305  			defer os.Remove(name)
   306  
   307  			n, err := io.Copy(f, resp.Body)
   308  			if err != nil {
   309  				return err
   310  			}
   311  
   312  			if _, err := f.Seek(0, io.SeekStart); err != nil {
   313  				return err
   314  			}
   315  
   316  			switch {
   317  			case strings.HasSuffix(base, ".zip"):
   318  				r, err := zip.NewReader(f, n)
   319  				if err != nil {
   320  					return err
   321  				}
   322  
   323  				for _, f := range r.File {
   324  					fi := f.FileInfo()
   325  					if fi.IsDir() {
   326  						if err := os.MkdirAll(filepath.Join(root, f.Name), 0770); err != nil {
   327  							return err
   328  						}
   329  
   330  						continue
   331  					}
   332  
   333  					if err := func() error {
   334  						rc, err := f.Open()
   335  						if err != nil {
   336  							return err
   337  						}
   338  
   339  						defer rc.Close()
   340  
   341  						file, err := os.OpenFile(filepath.Join(root, f.Name), os.O_CREATE|os.O_WRONLY, fi.Mode())
   342  						if err != nil {
   343  							return err
   344  						}
   345  
   346  						w := bufio.NewWriter(file)
   347  						if _, err = io.Copy(w, rc); err != nil {
   348  							return err
   349  						}
   350  
   351  						if err := w.Flush(); err != nil {
   352  							return err
   353  						}
   354  
   355  						return file.Close()
   356  					}(); err != nil {
   357  						return err
   358  					}
   359  				}
   360  				return nil
   361  			}
   362  			panic("internal error") //TODOOK
   363  		}(); err != nil {
   364  			fmt.Fprintln(os.Stderr, err)
   365  		}
   366  	}
   367  }
   368  
   369  func fail(s string, args ...interface{}) {
   370  	fmt.Fprintf(os.Stderr, s, args...)
   371  	os.Exit(1)
   372  }
   373  
   374  func main() {
   375  	env := os.Getenv("GO_GENERATE")
   376  	goarch := runtime.GOARCH
   377  	goos := runtime.GOOS
   378  	if s := os.Getenv("TARGET_GOOS"); s != "" {
   379  		goos = s
   380  	}
   381  	if s := os.Getenv("TARGET_GOARCH"); s != "" {
   382  		goarch = s
   383  	}
   384  	var more []string
   385  	if env != "" {
   386  		more = strings.Split(env, ",")
   387  	}
   388  	ndebug := []string{"-DNDEBUG"}
   389  	for _, v := range more {
   390  		if v == "-DSQLITE_DEBUG" {
   391  			ndebug = nil
   392  		}
   393  	}
   394  	more = append(more, ndebug...)
   395  	download()
   396  	// experimental pthreads support currently only on linux/amd64
   397  	if goos != "linux" || goarch != "amd64" {
   398  		configProduction = append(configProduction, "-DSQLITE_MUTEX_NOOP")
   399  		configTest = append(configTest, "-DSQLITE_MUTEX_NOOP")
   400  	}
   401  	switch goos {
   402  	case "linux", "freebsd":
   403  		configProduction = append(configProduction, "-DSQLITE_OS_UNIX=1")
   404  	case "darwin":
   405  		configProduction = append(configProduction,
   406  			"-DSQLITE_OS_UNIX=1",
   407  			"-DSQLITE_WITHOUT_ZONEMALLOC",
   408  		)
   409  		configTest = append(configTest,
   410  			"-DSQLITE_OS_UNIX=1",
   411  			"-DSQLITE_WITHOUT_ZONEMALLOC",
   412  		)
   413  	case "windows":
   414  		configProduction = append(configProduction,
   415  			"-DSQLITE_OS_WIN=1",
   416  			"-D_MSC_VER=1900",
   417  		)
   418  		configTest = append(configTest,
   419  			"-DSQLITE_OS_WIN=1",
   420  			"-D_MSC_VER=1900",
   421  		)
   422  	default:
   423  		fail("unknows/unsupported os: %s\n", goos)
   424  	}
   425  	makeSqliteProduction(goos, goarch, more)
   426  	makeSqliteTest(goos, goarch, more)
   427  	makeMpTest(goos, goarch, more)
   428  	makeSpeedTest(goos, goarch, more)
   429  	makeTestfixture(goos, goarch, more)
   430  	ccgo.MustCopyDir(true, "testdata/tcl", sqliteSrcDir+"/test", nil)
   431  	ccgo.MustCopyDir(true, "testdata/tcl", "testdata/overlay", nil)
   432  }
   433  
   434  func configure(goos, goarch string) {
   435  	wd, err := os.Getwd()
   436  	if err != nil {
   437  		fail("%s", err)
   438  	}
   439  
   440  	defer os.Chdir(wd)
   441  
   442  	if err := os.Chdir(sqliteSrcDir); err != nil {
   443  		fail("%s", err)
   444  	}
   445  
   446  	cmd := newCmd("make", "distclean")
   447  	cmd.Run()
   448  	var args []string
   449  	switch goos {
   450  	case "linux", "freebsd":
   451  		// nop
   452  	case "darwin":
   453  		args = append(args, "--with-tcl=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework")
   454  	case "windows":
   455  		switch goarch {
   456  		case "amd64":
   457  			args = append(args, "--host=x86_64-w64-mingw32")
   458  		case "386":
   459  			args = append(args, "--host=i686-w64-mingw32")
   460  		default:
   461  			fail("unknown/unsupported os/arch: %s/%s\n", goos, goarch)
   462  		}
   463  	default:
   464  		fail("unknown/unsupported os/arch: %s/%s\n", goos, goarch)
   465  	}
   466  	cmd = newCmd("./configure", args...)
   467  	if err = cmd.Run(); err != nil {
   468  		fail("%s\n", err)
   469  	}
   470  
   471  	cmd = newCmd("make", "parse.h", "opcodes.h")
   472  	if err = cmd.Run(); err != nil {
   473  		fail("%s\n", err)
   474  	}
   475  }
   476  
   477  func newCmd(bin string, args ...string) *exec.Cmd {
   478  	fmt.Printf("==== newCmd %s\n", bin)
   479  	for _, v := range args {
   480  		fmt.Printf("\t%v\n", v)
   481  	}
   482  	r := exec.Command(bin, args...)
   483  	r.Stdout = os.Stdout
   484  	r.Stderr = os.Stderr
   485  	return r
   486  }
   487  
   488  func makeTestfixture(goos, goarch string, more []string) {
   489  	dir := filepath.FromSlash(fmt.Sprintf("internal/testfixture"))
   490  	files := []string{
   491  		"ext/expert/sqlite3expert.c",
   492  		"ext/expert/test_expert.c",
   493  		"ext/fts3/fts3_term.c",
   494  		"ext/fts3/fts3_test.c",
   495  		"ext/fts5/fts5_tcl.c",
   496  		"ext/fts5/fts5_test_mi.c",
   497  		"ext/fts5/fts5_test_tok.c",
   498  		"ext/misc/appendvfs.c",
   499  		"ext/misc/amatch.c",
   500  		"ext/misc/carray.c",
   501  		"ext/misc/cksumvfs.c",
   502  		"ext/misc/closure.c",
   503  		"ext/misc/csv.c",
   504  		"ext/misc/decimal.c",
   505  		"ext/misc/eval.c",
   506  		"ext/misc/explain.c",
   507  		"ext/misc/fileio.c",
   508  		"ext/misc/fuzzer.c",
   509  		"ext/misc/ieee754.c",
   510  		"ext/misc/mmapwarm.c",
   511  		"ext/misc/nextchar.c",
   512  		"ext/misc/normalize.c",
   513  		"ext/misc/percentile.c",
   514  		"ext/misc/prefixes.c",
   515  		"ext/misc/regexp.c",
   516  		"ext/misc/remember.c",
   517  		"ext/misc/series.c",
   518  		"ext/misc/spellfix.c",
   519  		"ext/misc/totype.c",
   520  		"ext/misc/unionvtab.c",
   521  		"ext/misc/wholenumber.c",
   522  		"ext/misc/zipfile.c",
   523  		"ext/rbu/test_rbu.c",
   524  		"ext/session/test_session.c",
   525  		"ext/userauth/userauth.c",
   526  		"src/tclsqlite.c",
   527  		"src/test1.c",
   528  		"src/test2.c",
   529  		"src/test3.c",
   530  		"src/test4.c",
   531  		"src/test5.c",
   532  		"src/test6.c",
   533  		"src/test7.c",
   534  		"src/test8.c",
   535  		"src/test9.c",
   536  		"src/test_async.c",
   537  		"src/test_autoext.c",
   538  		"src/test_backup.c",
   539  		"src/test_bestindex.c",
   540  		"src/test_blob.c",
   541  		"src/test_btree.c",
   542  		"src/test_config.c",
   543  		"src/test_delete.c",
   544  		"src/test_demovfs.c",
   545  		"src/test_devsym.c",
   546  		"src/test_fs.c",
   547  		"src/test_func.c",
   548  		"src/test_hexio.c",
   549  		"src/test_init.c",
   550  		"src/test_intarray.c",
   551  		"src/test_journal.c",
   552  		"src/test_malloc.c",
   553  		"src/test_md5.c",
   554  		"src/test_multiplex.c",
   555  		"src/test_mutex.c",
   556  		"src/test_onefile.c",
   557  		"src/test_osinst.c",
   558  		"src/test_pcache.c",
   559  		"src/test_quota.c",
   560  		"src/test_rtree.c",
   561  		"src/test_schema.c",
   562  		"src/test_server.c",
   563  		"src/test_superlock.c",
   564  		"src/test_syscall.c",
   565  		"src/test_tclsh.c",
   566  		"src/test_tclvar.c",
   567  		"src/test_thread.c",
   568  		"src/test_vdbecov.c",
   569  		"src/test_vfs.c",
   570  		"src/test_windirent.c",
   571  		"src/test_window.c",
   572  		"src/test_wsd.c",
   573  	}
   574  	for i, v := range files {
   575  		files[i] = filepath.Join(sqliteSrcDir, filepath.FromSlash(v))
   576  	}
   577  	configure(goos, goarch)
   578  
   579  	args := join(
   580  		[]string{
   581  			"ccgo",
   582  			"-DSQLITE_OMIT_LOAD_EXTENSION",
   583  			"-DSQLITE_SERIES_CONSTRAINT_VERIFY=1",
   584  			"-DSQLITE_SERVER=1",
   585  			"-DTCLSH_INIT_PROC=sqlite3TestInit",
   586  			"-D_HAVE_SQLITE_CONFIG_H",
   587  			"-I/usr/include/tcl8.6", //TODO should not be hardcoded
   588  			"-export-defines", "",
   589  			"-export-fields", "F",
   590  			"-trace-translation-units",
   591  			volatiles,
   592  			"-lmodernc.org/sqlite/libtest",
   593  			"-lmodernc.org/tcl/lib",
   594  			"-lmodernc.org/z/lib",
   595  			"-o", filepath.Join(dir, fmt.Sprintf("testfixture_%s_%s.go", goos, goarch)),
   596  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/async"))),
   597  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/fts3"))),
   598  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/icu"))),
   599  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/rtree"))),
   600  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/session"))),
   601  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("ext/userauth"))),
   602  			fmt.Sprintf("-I%s", filepath.Join(sqliteSrcDir, filepath.FromSlash("src"))),
   603  			fmt.Sprintf("-I%s", sqliteDir),
   604  			fmt.Sprintf("-I%s", sqliteSrcDir),
   605  		},
   606  		files,
   607  		more,
   608  		configTest,
   609  	)
   610  	// experimental pthreads support currently only on linux/amd64
   611  	if goos != "linux" || goarch != "amd64" {
   612  		args = append(args, "-lmodernc.org/sqlite/internal/libc2")
   613  	}
   614  	task := ccgo.NewTask(args, nil, nil)
   615  	if err := task.Main(); err != nil {
   616  		fail("%s\n", err)
   617  	}
   618  }
   619  
   620  func makeSpeedTest(goos, goarch string, more []string) {
   621  	task := ccgo.NewTask(
   622  		join(
   623  			[]string{
   624  				"ccgo",
   625  				"-export-defines", "",
   626  				"-o", filepath.FromSlash(fmt.Sprintf("speedtest1/main_%s_%s.go", goos, goarch)),
   627  				"-trace-translation-units",
   628  				filepath.Join(sqliteSrcDir, "test", "speedtest1.c"),
   629  				fmt.Sprintf("-I%s", sqliteDir),
   630  				"-l", "modernc.org/sqlite/lib",
   631  			},
   632  			more,
   633  			configProduction,
   634  		),
   635  		nil,
   636  		nil,
   637  	)
   638  	if err := task.Main(); err != nil {
   639  		fail("%s\n", err)
   640  	}
   641  }
   642  
   643  func makeMpTest(goos, goarch string, more []string) {
   644  	task := ccgo.NewTask(
   645  		join(
   646  			[]string{
   647  				"ccgo",
   648  				"-export-defines", "",
   649  				"-o", filepath.FromSlash(fmt.Sprintf("internal/mptest/main_%s_%s.go", goos, goarch)),
   650  				"-trace-translation-units",
   651  				filepath.Join(sqliteSrcDir, "mptest", "mptest.c"),
   652  				fmt.Sprintf("-I%s", sqliteDir),
   653  				"-l", "modernc.org/sqlite/lib",
   654  			},
   655  			more,
   656  			configProduction,
   657  		),
   658  		nil,
   659  		nil,
   660  	)
   661  	if err := task.Main(); err != nil {
   662  		fail("%s\n", err)
   663  	}
   664  }
   665  
   666  func makeSqliteProduction(goos, goarch string, more []string) {
   667  	task := ccgo.NewTask(
   668  		join(
   669  			[]string{
   670  				"ccgo",
   671  				"-DSQLITE_PRIVATE=",
   672  				"-export-defines", "",
   673  				"-export-enums", "",
   674  				"-export-externs", "X",
   675  				"-export-fields", "F",
   676  				"-export-typedefs", "",
   677  				"-pkgname", "sqlite3",
   678  				"-o", filepath.FromSlash(fmt.Sprintf("lib/sqlite_%s_%s.go", goos, goarch)),
   679  				"-trace-translation-units",
   680  				filepath.Join(sqliteDir, "sqlite3.c"),
   681  			},
   682  			more,
   683  			configProduction,
   684  		),
   685  		nil,
   686  		nil,
   687  	)
   688  	if err := task.Main(); err != nil {
   689  		fail("%s\n", err)
   690  	}
   691  }
   692  
   693  func makeSqliteTest(goos, goarch string, more []string) {
   694  	task := ccgo.NewTask(
   695  		join(
   696  			[]string{
   697  				"ccgo",
   698  				"-DSQLITE_PRIVATE=",
   699  				"-export-defines", "",
   700  				"-export-enums", "",
   701  				"-export-externs", "X",
   702  				"-export-fields", "F",
   703  				"-export-typedefs", "",
   704  				"-pkgname", "sqlite3",
   705  				"-o", filepath.FromSlash(fmt.Sprintf("libtest/sqlite_%s_%s.go", goos, goarch)),
   706  				"-trace-translation-units",
   707  				volatiles,
   708  				filepath.Join(sqliteDir, "sqlite3.c"),
   709  			},
   710  			more,
   711  			configTest,
   712  		),
   713  		nil,
   714  		nil,
   715  	)
   716  	if err := task.Main(); err != nil {
   717  		fail("%s\n", err)
   718  	}
   719  }
   720  
   721  func join(a ...[]string) (r []string) {
   722  	n := 0
   723  	for _, v := range a {
   724  		n += len(v)
   725  	}
   726  	r = make([]string, 0, n)
   727  	for _, v := range a {
   728  		r = append(r, v...)
   729  	}
   730  	return r
   731  }