File
Blob: build/BUILD.sqlite3
| 1 | """ |
| 2 | Builds sqlite3 from plain source. |
| 3 | |
| 4 | This is just enough to build the sqlite3 library; it does not include |
| 5 | the shell or any other utilities. |
| 6 | """ |
| 7 | |
| 8 | load("@rules_cc//cc:cc_binary.bzl", "cc_binary") |
| 9 | load("@rules_cc//cc:cc_library.bzl", "cc_library") |
| 10 | |
| 11 | package(default_visibility = ["//visibility:private"]) |
| 12 | |
| 13 | SQLITE_DEFINES = [ |
| 14 | "SQLITE_MAX_ALLOCATION_SIZE=16777216", # 16MB |
| 15 | "SQLITE_PRINTF_PRECISION_LIMIT=100000", |
| 16 | "SQLITE_ENABLE_FTS5", |
| 17 | "SQLITE_ENABLE_NORMALIZE", |
| 18 | "SQLITE_ENABLE_MATH_FUNCTIONS", |
| 19 | "SQLITE_DEFAULT_FOREIGN_KEYS=1", |
| 20 | "SQLITE_ENABLE_UPDATE_DELETE_LIMIT", |
| 21 | "SQLITE_OMIT_SHARED_CACHE", |
| 22 | ] |
| 23 | |
| 24 | SQLITE_DEFINES_FOR_LEMON = " ".join(["-D" + x for x in SQLITE_DEFINES]) |
| 25 | |
| 26 | GIVEN_SOURCES = glob([ |
| 27 | "src/**/*.h", |
| 28 | "src/**/*.c", |
| 29 | "ext/**/*.h", |
| 30 | "ext/**/*.c", |
| 31 | ]) |
| 32 | |
| 33 | GENERATED_SOURCES = [] |
| 34 | |
| 35 | # Regarding src/vdbe.c: In the normal SQLite build process, the given |
| 36 | # src/vdbe.c is run through tool/vdbe-compress.tcl before use. There |
| 37 | # is an amalgamation-build-time option called SQLITE_SMALL_STACK; if |
| 38 | # this option is not given, then vdbe-compress.tcl does nothing; it |
| 39 | # just emits its input verbatim. |
| 40 | # |
| 41 | # We have not set SQLITE_SMALL_STACK, so this Bazel-build file does |
| 42 | # not bother with tool/vdbe-compress.tcl. |
| 43 | |
| 44 | cc_binary( |
| 45 | name = "lemon", |
| 46 | srcs = ["tool/lemon.c"], |
| 47 | copts = ["-w"], |
| 48 | ) |
| 49 | |
| 50 | # ======================================================================== |
| 51 | # Constructs parse.{c,h} using the Lemon parser generator. |
| 52 | |
| 53 | genrule( |
| 54 | name = "parse_ch", |
| 55 | srcs = [ |
| 56 | "src/parse.y", |
| 57 | "tool/lempar.c", |
| 58 | ], |
| 59 | outs = [ |
| 60 | "parse.h", |
| 61 | "parse.c", |
| 62 | ], |
| 63 | cmd = ( |
| 64 | # lemon requires lempar.c to be in the current working |
| 65 | # directory, and parse.y has to be in a writable directory |
| 66 | # since the output files are created adjacent to it. |
| 67 | "cp $(SRCS) . " + |
| 68 | |
| 69 | # Creates parse.c and parse.h |
| 70 | "&& $(execpath :lemon) {} parse.y ".format(SQLITE_DEFINES_FOR_LEMON) + |
| 71 | |
| 72 | # Bazel expects genrule outputs to be in RULEDIR |
| 73 | "&& cp parse.h parse.c $(RULEDIR)" |
| 74 | ), |
| 75 | tools = [ |
| 76 | ":lemon", |
| 77 | ], |
| 78 | ) |
| 79 | |
| 80 | GENERATED_SOURCES += [ |
| 81 | "parse.h", |
| 82 | "parse.c", |
| 83 | ] |
| 84 | |
| 85 | # ======================================================================== |
| 86 | # Constructs fts5parse.{c,h} using the Lemon parser generator. |
| 87 | |
| 88 | genrule( |
| 89 | name = "fts5parse_ch", |
| 90 | srcs = [ |
| 91 | "ext/fts5/fts5parse.y", |
| 92 | "tool/lempar.c", |
| 93 | ], |
| 94 | outs = [ |
| 95 | "fts5parse.h", |
| 96 | "fts5parse.c", |
| 97 | ], |
| 98 | cmd = ( |
| 99 | # Same as :parse_ch |
| 100 | "cp $(SRCS) . " + |
| 101 | "&& $(execpath :lemon) {} fts5parse.y ".format(SQLITE_DEFINES_FOR_LEMON) + |
| 102 | # Bazel expects genrule outputs to be in RULEDIR |
| 103 | "&& cp fts5parse.h fts5parse.c $(RULEDIR)" |
| 104 | ), |
| 105 | tools = [ |
| 106 | ":lemon", |
| 107 | ], |
| 108 | ) |
| 109 | |
| 110 | GENERATED_SOURCES += [ |
| 111 | "fts5parse.h", |
| 112 | "fts5parse.c", |
| 113 | ] |
| 114 | |
| 115 | # ======================================================================== |
| 116 | # Constructs fts5.{c,h}. "FTS5" is version 5 of Full Text Search. |
| 117 | |
| 118 | filegroup( |
| 119 | name = "fts5_sources", |
| 120 | srcs = glob([ |
| 121 | "ext/fts5/*.h", |
| 122 | "ext/fts5/*.c", |
| 123 | ]), |
| 124 | ) |
| 125 | |
| 126 | genrule( |
| 127 | name = "fts5_ch", |
| 128 | srcs = [ |
| 129 | "fts5parse.h", |
| 130 | "fts5parse.c", |
| 131 | "manifest", |
| 132 | "manifest.uuid", |
| 133 | ":fts5_sources", |
| 134 | ], |
| 135 | outs = [ |
| 136 | "fts5.h", |
| 137 | "fts5.c", |
| 138 | ], |
| 139 | cmd = ( |
| 140 | "mkdir -p $(RULEDIR)/build/ext/fts5/tool " + |
| 141 | |
| 142 | # Copy all the inputs over so the directory structure is to |
| 143 | # mkfts5c.tcl's liking. This ends up putting everything not in |
| 144 | # :fts5_sources in there twice, once in build/ and once in |
| 145 | # build/ext/fts5/, but it doesn't hurt anything. :shrug: |
| 146 | "&& cp $(SRCS) $(RULEDIR)/build/ext/fts5 " + |
| 147 | "&& cp $(location manifest) $(RULEDIR)/build " + |
| 148 | "&& cp $(location manifest.uuid) $(RULEDIR)/build " + |
| 149 | "&& cp $(location fts5parse.h) $(RULEDIR)/build " + |
| 150 | "&& cp $(location fts5parse.c) $(RULEDIR)/build " + |
| 151 | "&& cp $(location ext/fts5/tool/mkfts5c.tcl) $(RULEDIR)/build/ext/fts5/tool " + |
| 152 | |
| 153 | # Okay, go. |
| 154 | "&& pushd $(RULEDIR)/build >/dev/null " + |
| 155 | "&& tclsh ext/fts5/tool/mkfts5c.tcl " + |
| 156 | "&& popd >/dev/null " + |
| 157 | |
| 158 | # Put the outputs where Bazel will see them. |
| 159 | "&& mv $(RULEDIR)/build/fts5.c $(RULEDIR)/build/ext/fts5/fts5.h $(RULEDIR) " + |
| 160 | |
| 161 | # Done. Clean up after ourselves. |
| 162 | "&& rm -r $(RULEDIR)/build" |
| 163 | ), |
| 164 | tools = [ |
| 165 | "ext/fts5/tool/mkfts5c.tcl", |
| 166 | ], |
| 167 | ) |
| 168 | |
| 169 | GENERATED_SOURCES += ["fts5.c"] |
| 170 | |
| 171 | # ======================================================================== |
| 172 | # These rules construct various source files using provided utility programs. |
| 173 | |
| 174 | genrule( |
| 175 | name = "opcodes_h", |
| 176 | srcs = [ |
| 177 | "parse.h", |
| 178 | "src/vdbe.c", |
| 179 | ], |
| 180 | outs = ["opcodes.h"], |
| 181 | cmd = "cat $(location parse.h) $(location src/vdbe.c) | tclsh $(location tool/mkopcodeh.tcl) > $(RULEDIR)/opcodes.h", |
| 182 | tools = ["tool/mkopcodeh.tcl"], |
| 183 | ) |
| 184 | |
| 185 | GENERATED_SOURCES += ["opcodes.h"] |
| 186 | |
| 187 | genrule( |
| 188 | name = "opcodes_c", |
| 189 | srcs = ["opcodes.h"], |
| 190 | outs = ["opcodes.c"], |
| 191 | cmd = "tclsh $(location tool/mkopcodec.tcl) $(location opcodes.h) > $(RULEDIR)/opcodes.c", |
| 192 | tools = ["tool/mkopcodec.tcl"], |
| 193 | ) |
| 194 | |
| 195 | GENERATED_SOURCES += ["opcodes.c"] |
| 196 | |
| 197 | cc_binary( |
| 198 | name = "mkkeywordhash", |
| 199 | srcs = ["tool/mkkeywordhash.c"], |
| 200 | copts = ["-w"], |
| 201 | ) |
| 202 | |
| 203 | genrule( |
| 204 | name = "keywordhash_h", |
| 205 | outs = ["keywordhash.h"], |
| 206 | cmd = "$(execpath :mkkeywordhash) > $(RULEDIR)/keywordhash.h", |
| 207 | tools = [":mkkeywordhash"], |
| 208 | ) |
| 209 | |
| 210 | GENERATED_SOURCES += ["keywordhash.h"] |
| 211 | |
| 212 | # ======================================================================== |
| 213 | # Constructs sqlite3.h. |
| 214 | |
| 215 | cc_binary( |
| 216 | name = "mksourceid", |
| 217 | srcs = ["tool/mksourceid.c"], |
| 218 | copts = ["-w"], |
| 219 | ) |
| 220 | |
| 221 | genrule( |
| 222 | name = "sqlite3_h", |
| 223 | srcs = [ |
| 224 | # The first few dependencies come from the "sqlite3.h" target |
| 225 | # in main.mk in the SQLite source distribution. |
| 226 | "src/sqlite.h.in", |
| 227 | "manifest", |
| 228 | "VERSION", |
| 229 | "ext/rtree/sqlite3rtree.h", |
| 230 | |
| 231 | # These come from looking for "set filelist" in mksqlite3h.tcl |
| 232 | # and looking for files not named above. The script fails with |
| 233 | # a complaint about a missing file if these aren't here. |
| 234 | "ext/session/sqlite3session.h", |
| 235 | "ext/fts5/fts5.h", |
| 236 | ], |
| 237 | outs = ["sqlite3.h"], |
| 238 | |
| 239 | # mksqlite3h.tcl expects to run in a directory with a very |
| 240 | # particular structure, so we have to set that up for it. |
| 241 | # |
| 242 | # We use $(RULEDIR)/build since RULEDIR is guaranteed to be |
| 243 | # writable. |
| 244 | cmd = ( |
| 245 | "mkdir -p $(RULEDIR)/build/src $(RULEDIR)/build/ext/rtree $(RULEDIR)/build/ext/session $(RULEDIR)/build/ext/fts5 " + |
| 246 | |
| 247 | # TODO(cleanup): come up with a less-repetitive way to do this. |
| 248 | "&& cp $(location tool/mksqlite3h.tcl) $(RULEDIR)/build " + |
| 249 | "&& cp $(location src/sqlite.h.in) $(RULEDIR)/build/src/sqlite.h.in " + |
| 250 | "&& cp $(location manifest) $(RULEDIR)/build/manifest " + |
| 251 | "&& cp $(location VERSION) $(RULEDIR)/build/VERSION " + |
| 252 | "&& cp $(location ext/rtree/sqlite3rtree.h) $(RULEDIR)/build/ext/rtree/sqlite3rtree.h " + |
| 253 | "&& cp $(location ext/session/sqlite3session.h) $(RULEDIR)/build/ext/session/sqlite3session.h " + |
| 254 | "&& cp $(location ext/fts5/fts5.h) $(RULEDIR)/build/ext/fts5/fts5.h " + |
| 255 | |
| 256 | # It also expects to invoke mksourceid. |
| 257 | "&& cp $(execpath :mksourceid) $(RULEDIR)/build/mksourceid " + |
| 258 | |
| 259 | # Okay, go. |
| 260 | "&& pushd $(RULEDIR)/build >/dev/null " + |
| 261 | "&& tclsh mksqlite3h.tcl . > ../sqlite3.h " + |
| 262 | "&& popd >/dev/null " + |
| 263 | |
| 264 | # Done. Clean up after ourselves. |
| 265 | "&& rm -r $(RULEDIR)/build" |
| 266 | ), |
| 267 | tools = [ |
| 268 | "tool/mksqlite3h.tcl", |
| 269 | ":mksourceid", |
| 270 | ], |
| 271 | ) |
| 272 | |
| 273 | GENERATED_SOURCES += ["sqlite3.h"] |
| 274 | |
| 275 | # ======================================================================== |
| 276 | # Constructs the amalgamation. Well, the rest of it; sqlite3.h is one |
| 277 | # of the files in the amalgamation. |
| 278 | |
| 279 | genrule( |
| 280 | name = "amalgamation", |
| 281 | srcs = GIVEN_SOURCES + GENERATED_SOURCES, |
| 282 | outs = [ |
| 283 | "sqlite3.c", |
| 284 | "sqlite3ext.h", |
| 285 | ], |
| 286 | |
| 287 | # mksqlite3c.tcl expects to run in a directory with a very |
| 288 | # particular structure, so we have to set that up for it. |
| 289 | # |
| 290 | # We use $(RULEDIR)/build/tsrc since RULEDIR is guaranteed to be |
| 291 | # writable. ("tsrc" matches the directory name in the SQLite |
| 292 | # Makefile.) |
| 293 | cmd = ( |
| 294 | "mkdir -p $(RULEDIR)/build/tsrc $(RULEDIR)/build/tool " + |
| 295 | |
| 296 | # Copy everything in. There's no subdirectories; everything |
| 297 | # but mksqlite3c.tcl just goes in tsrc. |
| 298 | "&& cp $(SRCS) $(RULEDIR)/build/tsrc " + |
| 299 | "&& cp $(location tool/mksqlite3c.tcl) $(RULEDIR)/build/tool " + |
| 300 | |
| 301 | # Build the thing. |
| 302 | # |
| 303 | # This step ("make sqlite3c") is where the SQLite Makefile |
| 304 | # would also construct tclsqlite3.c, but we don't use that |
| 305 | # file, so we don't bother building it. |
| 306 | "&& pushd $(RULEDIR)/build >/dev/null " + |
| 307 | "&& tclsh tool/mksqlite3c.tcl " + |
| 308 | "&& popd >/dev/null " + |
| 309 | |
| 310 | # Copy the outputs somewhere that Bazel will find them. |
| 311 | "&& cp $(RULEDIR)/build/sqlite3.c $(RULEDIR)/build/tsrc/sqlite3ext.h $(RULEDIR)/ " + |
| 312 | |
| 313 | # Done. Clean up after ourselves. |
| 314 | "&& rm -r $(RULEDIR)/build" |
| 315 | ), |
| 316 | tools = [ |
| 317 | "tool/mksqlite3c.tcl", |
| 318 | ], |
| 319 | ) |
| 320 | # ======================================================================== |
| 321 | # Actually builds the library. |
| 322 | |
| 323 | cc_library( |
| 324 | name = "sqlite3", |
| 325 | srcs = ["sqlite3.c"], |
| 326 | hdrs = [ |
| 327 | "sqlite3.h", |
| 328 | "sqlite3ext.h", |
| 329 | ], |
| 330 | copts = ["-w"], # Ignore all warnings. This is not our code, we can't fix the warnings. |
| 331 | defines = SQLITE_DEFINES, |
| 332 | include_prefix = ".", |
| 333 | visibility = ["//visibility:public"], |
| 334 | ) |