sqlite_web_vfs 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 285cd03d979c57d50cbe483330d345f16eaa4eefcdc7e3672c7d4d2717dc6dfd
4
+ data.tar.gz: 4111ca88772ffa0e35f6807fcadbd3905a058d9bffb8352c59a12c7feba01d30
5
+ SHA512:
6
+ metadata.gz: 4b465bd199fd173480be78be31c866cfeedc8ec4bbb88225f56c73f51a70bc98fa14e2360fc5224f2151e633e6b58a2b01dc93e7a5c112b0b15079bcd6caf7aa
7
+ data.tar.gz: 1731b2b7c91d9606eafdf8ccdfcf959ef2dd08ddcf6e12dd0a0c24e4d1d70b32b1fe5eada7067f8ba5d6a73a04c7bf754928abf08275615a68c0736563b77a0c
@@ -0,0 +1,32 @@
1
+ This gem vendors C/C++ sources from mlin/sqlite_web_vfs.
2
+
3
+ Upstream license (from mlin/sqlite_web_vfs/LICENSE):
4
+
5
+ ----------------------------------------
6
+ Copyright (c) 2023-2024, Mike Lin
7
+ All rights reserved.
8
+
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions are met:
11
+
12
+ 1. Redistributions of source code must retain the above copyright notice,
13
+ this list of conditions and the following disclaimer.
14
+ 2. Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+ 3. Neither the name of the copyright holder nor the names of its
18
+ contributors may be used to endorse or promote products derived from
19
+ this software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ ----------------------------------------
32
+
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # sqlite_web_vfs (Ruby gem)
2
+
3
+ This gem builds and loads the HTTP VFS from mlin/sqlite_web_vfs as a Ruby native extension (no CMake), and exposes a small loader helper to use it from both `sqlite3` and `sqlite3-ffi`.
4
+
5
+ Note: This gem includes code from mlin/sqlite_web_vfs, used under its original license.
6
+
7
+ ## Features
8
+ - Wraps upstream C/C++ sources without modification (vendored in `ext/sqlite_web_vfs/upstream/`).
9
+ - Builds with `mkmf` and auto-detects SQLite via `pkg-config` or flags.
10
+ - macOS (Homebrew) and Amazon Linux 2023 supported.
11
+ - Optional, opt-in bundled SQLite amalgamation: `WEBVFS_FORCE_BUNDLED=1`.
12
+ - Loader works with both `sqlite3` and `sqlite3-ffi`.
13
+
14
+ ## Install
15
+ - macOS (Homebrew): `brew install sqlite curl`
16
+ - Amazon Linux 2023: `sudo dnf install sqlite-devel libcurl-devel`
17
+
18
+ Then:
19
+
20
+ ```
21
+ gem build sqlite_web_vfs.gemspec
22
+ gem install ./sqlite_web_vfs-*.gem
23
+ ```
24
+
25
+ If SQLite isn’t found, you can point to it:
26
+
27
+ ```
28
+ gem install sqlite_web_vfs -- --with-sqlite3-dir=/usr/local/opt/sqlite
29
+ ```
30
+
31
+ Advanced option: bundle SQLite amalgamation inside the extension (may not interoperate with other SQLite users in the same process):
32
+
33
+ ```
34
+ WEBVFS_FORCE_BUNDLED=1 gem install sqlite_web_vfs
35
+ ```
36
+
37
+ ## Security
38
+ Loading extensions can execute arbitrary native code. Only load trusted extensions from trusted locations and review your supply chain.
39
+
40
+ ## Runtime API examples
41
+
42
+ ### 1. Usage with `sqlite3`
43
+
44
+ ```ruby
45
+ require 'sqlite3'
46
+ require 'sqlite_web_vfs'
47
+ require 'uri'
48
+
49
+ chinook_url = "https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite"
50
+ encoded_url = URI.encode_www_form_component(chinook_url)
51
+ web_uri = "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}"
52
+
53
+ db = SQLite3::Database.new(':memory:')
54
+ SQLiteWebVFS::Loader.load(db)
55
+ puts "HTTP VFS extension loaded."
56
+
57
+ db.execute("ATTACH DATABASE ? AS remote", [web_uri])
58
+ puts "Remote database attached as 'remote'."
59
+
60
+ album_count = db.get_first_value("SELECT COUNT(*) FROM remote.Album")
61
+ puts "Found #{album_count} albums in the remote Chinook database."
62
+ ```
63
+
64
+ ### 2. Usage with `sqlite3-ffi`
65
+
66
+ ```ruby
67
+ require 'sqlite3-ffi'
68
+ require 'sqlite_web_vfs'
69
+ require 'uri'
70
+
71
+ chinook_url = "https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite"
72
+ encoded_url = URI.encode_www_form_component(chinook_url)
73
+ web_uri = "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}"
74
+
75
+ db = SQLite3::Database.new(':memory:')
76
+ SQLiteWebVFS::Loader.load(db)
77
+ puts "HTTP VFS extension loaded into FFI driver."
78
+
79
+ db.execute("ATTACH DATABASE ? AS remote", [web_uri])
80
+ puts "Remote database attached as 'remote'."
81
+
82
+ album_count = db.execute("SELECT COUNT(*) FROM remote.Album").first.first
83
+ puts "Found #{album_count} albums in the remote Chinook database."
84
+ ```
85
+
86
+ ### 3. Usage with SQLite CLI
87
+
88
+ **Note**: Extension loading requires SQLite to be compiled with extension support. Many system SQLite builds disable this for security (compiled with `OMIT_LOAD_EXTENSION`). If `.load` is unavailable, use the Ruby examples above instead.
89
+
90
+ For SQLite builds with extension support (use Homebrew's sqlite3 on macOS):
91
+
92
+ ```bash
93
+ # macOS: Use Homebrew's sqlite3 which supports extensions
94
+ /opt/homebrew/bin/sqlite3 -cmd ".load $(ruby -r sqlite_web_vfs -e 'puts SQLiteWebVFS::Loader.built_extension_path')" -cmd "ATTACH DATABASE 'file:/__web__?vfs=web&mode=ro&immutable=1&web_url=https%3A//github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite' AS remote;" ":memory:"
95
+
96
+ # Or with PATH updated to use Homebrew's sqlite3:
97
+ sqlite3 -cmd ".load $(ruby -r sqlite_web_vfs -e 'puts SQLiteWebVFS::Loader.built_extension_path')" -cmd "ATTACH DATABASE 'file:/__web__?vfs=web&mode=ro&immutable=1&web_url=https%3A//github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite' AS remote;" ":memory:"
98
+ ```
99
+
100
+ Then query the remote database:
101
+ ```sql
102
+ SELECT COUNT(*) FROM remote.Album;
103
+ ```
104
+
105
+ To check if your SQLite supports extensions:
106
+ ```bash
107
+ sqlite3 ":memory:" "PRAGMA compile_options;" | grep -i load
108
+ ```
109
+ If you see `OMIT_LOAD_EXTENSION`, use the Ruby API instead.
110
+
111
+ ## Development
112
+ - Build: `gem build` then install the gem.
113
+ - Tests: `bundle exec rspec` (CI runs on Amazon Linux 2023 and macOS).
114
+
115
+ ## License
116
+ - Vendored C/C++ from `mlin/sqlite_web_vfs`. See `LICENSE-3RD-PARTY.md`.
117
+ - This gem includes code from `mlin/sqlite_web_vfs`, used under its original license.
118
+
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sqlite3'
4
+ require 'sqlite_web_vfs'
5
+ require 'uri'
6
+
7
+ chinook_url = 'https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite'
8
+ encoded_url = URI.encode_www_form_component(chinook_url)
9
+ web_uri = "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}"
10
+
11
+ db = SQLite3::Database.new(':memory:')
12
+ SQLiteWebVFS::Loader.load(db)
13
+ puts '✅ HTTP VFS extension loaded.'
14
+
15
+ db.execute('ATTACH DATABASE ? AS remote', [web_uri])
16
+ puts "✅ Remote database attached as 'remote'."
17
+
18
+ album_count = db.get_first_value('SELECT COUNT(*) FROM remote.Album')
19
+ puts "💿 Found #{album_count} albums in the remote Chinook database."
20
+
21
+ db.close
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'sqlite3-ffi'
5
+ rescue LoadError
6
+ require 'sqlite3/ffi'
7
+ end
8
+ require 'sqlite_web_vfs'
9
+ require 'uri'
10
+
11
+ chinook_url = 'https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite'
12
+ encoded_url = URI.encode_www_form_component(chinook_url)
13
+ web_uri = "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}"
14
+
15
+ db = SQLite3::Database.new(':memory:')
16
+ SQLiteWebVFS::Loader.load(db)
17
+ puts '✅ HTTP VFS extension loaded into FFI driver.'
18
+
19
+ db.execute('ATTACH DATABASE ? AS remote', [web_uri])
20
+ puts "✅ Remote database attached as 'remote'."
21
+
22
+ album_count = db.execute('SELECT COUNT(*) FROM remote.Album').first.first
23
+ puts "💿 Found #{album_count} albums in the remote Chinook database."
24
+
25
+ db.close
@@ -0,0 +1,267 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ ECHO1 = $(V:1=@ :)
9
+ ECHO = $(ECHO1:0=@ echo)
10
+ NULLCMD = :
11
+
12
+ #### Start of system configuration section. ####
13
+
14
+ srcdir = .
15
+ topdir = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0
16
+ hdrdir = $(topdir)
17
+ arch_hdrdir = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/universal-darwin24
18
+ PATH_SEPARATOR = :
19
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
20
+ prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr
21
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
22
+ rubyarchprefix = $(rubylibprefix)/$(arch)
23
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
24
+ exec_prefix = $(prefix)
25
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
26
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
27
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
28
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
29
+ sitehdrdir = $(rubyhdrdir)/site_ruby
30
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
31
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
32
+ vendorlibdir = $(vendordir)/$(ruby_version)
33
+ vendordir = $(rubylibprefix)/vendor_ruby
34
+ sitearchdir = $(sitelibdir)/$(sitearch)
35
+ sitelibdir = $(sitedir)/$(ruby_version)
36
+ sitedir = $(DESTDIR)/Library/Ruby/Site
37
+ rubyarchdir = $(rubylibdir)/$(arch)
38
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
39
+ sitearchincludedir = $(includedir)/$(sitearch)
40
+ archincludedir = $(includedir)/$(arch)
41
+ sitearchlibdir = $(libdir)/$(sitearch)
42
+ archlibdir = $(libdir)/$(arch)
43
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
44
+ mandir = $(DESTDIR)/usr/share/man
45
+ localedir = $(datarootdir)/locale
46
+ libdir = $(exec_prefix)/lib
47
+ psdir = $(docdir)
48
+ pdfdir = $(docdir)
49
+ dvidir = $(docdir)
50
+ htmldir = $(docdir)
51
+ infodir = $(DESTDIR)/usr/share/info
52
+ docdir = $(datarootdir)/doc/$(PACKAGE)
53
+ oldincludedir = $(DESTDIR)/usr/include
54
+ includedir = $(DESTDIR)/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk$(prefix)/include
55
+ runstatedir = $(localstatedir)/run
56
+ localstatedir = $(prefix)/var
57
+ sharedstatedir = $(prefix)/com
58
+ sysconfdir = $(DESTDIR)/Library/Ruby/Site
59
+ datadir = $(datarootdir)
60
+ datarootdir = $(prefix)/share
61
+ libexecdir = $(exec_prefix)/libexec
62
+ sbindir = $(exec_prefix)/sbin
63
+ bindir = $(exec_prefix)/bin
64
+ archdir = $(rubyarchdir)
65
+
66
+
67
+ CC_WRAPPER =
68
+ CC = xcrun clang
69
+ CXX = xcrun clang++
70
+ LIBRUBY = $(LIBRUBY_SO)
71
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
72
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
73
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework Security -framework Foundation $(MAINLIBS)
74
+ empty =
75
+ OUTFLAG = -o $(empty)
76
+ COUTFLAG = -o $(empty)
77
+ CSRCFLAG = $(empty)
78
+
79
+ RUBY_EXTCONF_H =
80
+ cflags = $(optflags) $(debugflags) $(warnflags)
81
+ cxxflags = $(optflags) $(debugflags) $(warnflags)
82
+ optflags =
83
+ debugflags = -g
84
+ warnflags =
85
+ cppflags =
86
+ CCDLFLAGS =
87
+ CFLAGS = $(CCDLFLAGS) -g -Os -pipe -DHAVE_GCC_ATOMIC_BUILTINS -fno-typed-memory-operations -fno-typed-cxx-new-delete -DUSE_FFI_CLOSURE_ALLOC $(ARCH_FLAG)
88
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) -I/opt/homebrew/opt/sqlite/include
89
+ DEFS =
90
+ CPPFLAGS = -DHAVE_SQLITE3_H -DHAVE_CURL_CURL_H -I/Users/denis/Documents/labtiva/sqlite_web_vfs/ext/sqlite_web_vfs/upstream/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags)
91
+ CXXFLAGS = $(CCDLFLAGS) -g -Os -pipe $(ARCH_FLAG)
92
+ ldflags = -L. -L/AppleInternal/Library/BuildRoots/4~B5FAugAunRW9OK7YcFNXDBTTVy6DXTYoxzE3ORQ/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.6.Internal.sdk/usr/local/lib -L/opt/homebrew/opt/sqlite/lib
93
+ dldflags = $(ARCH_FLAG) -undefined dynamic_lookup
94
+ ARCH_FLAG =
95
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
96
+ LDSHARED = $(CC) -dynamic -bundle
97
+ LDSHAREDXX = $(CXX) -dynamic -bundle
98
+ AR = libtool -static
99
+ EXEEXT =
100
+
101
+ RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
102
+ RUBY_SO_NAME = ruby.2.6
103
+ RUBYW_INSTALL_NAME =
104
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
105
+ RUBYW_BASE_NAME = rubyw
106
+ RUBY_BASE_NAME = ruby
107
+
108
+ arch = universal-darwin24
109
+ sitearch = $(arch)
110
+ ruby_version = 2.6.0
111
+ ruby = $(bindir)/$(RUBY_BASE_NAME)
112
+ RUBY = $(ruby)
113
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h
114
+
115
+ RM = rm -f
116
+ RM_RF = $(RUBY) -run -e rm -- -rf
117
+ RMDIRS = rmdir -p
118
+ MAKEDIRS = mkdir -p
119
+ INSTALL = /usr/bin/install -c
120
+ INSTALL_PROG = $(INSTALL) -m 0755
121
+ INSTALL_DATA = $(INSTALL) -m 644
122
+ COPY = cp
123
+ TOUCH = exit >
124
+
125
+ #### End of system configuration section. ####
126
+
127
+ preload =
128
+ libpath = . $(libdir) /Users/denis/Documents/labtiva/sqlite_web_vfs/ext/sqlite_web_vfs/upstream/lib
129
+ LIBPATH = -L. -L$(libdir) -L/Users/denis/Documents/labtiva/sqlite_web_vfs/ext/sqlite_web_vfs/upstream/lib
130
+ DEFFILE =
131
+
132
+ CLEANFILES = mkmf.log
133
+ DISTCLEANFILES =
134
+ DISTCLEANDIRS =
135
+
136
+ extout =
137
+ extout_prefix =
138
+ target_prefix = /sqlite_web_vfs
139
+ LOCAL_LIBS =
140
+ LIBS = $(LIBRUBYARG_SHARED) -lcurl -lsqlite3 -lsqlite3
141
+ ORIG_SRCS = _wrap_web_vfs.cc shim.c
142
+ SRCS = $(ORIG_SRCS)
143
+ OBJS = _wrap_web_vfs.o shim.o
144
+ HDRS = $(srcdir)/readerwriterqueue.h
145
+ LOCAL_HDRS =
146
+ TARGET = sqlite_web_vfs
147
+ TARGET_NAME = sqlite_web_vfs
148
+ TARGET_ENTRY = Init_$(TARGET_NAME)
149
+ DLLIB = $(TARGET).bundle
150
+ EXTSTATIC =
151
+ STATIC_LIB =
152
+
153
+ TIMESTAMP_DIR = .
154
+ BINDIR = $(bindir)
155
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
156
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
157
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
158
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
159
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
160
+ TARGET_SO_DIR =
161
+ TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
162
+ CLEANLIBS = $(TARGET_SO)
163
+ CLEANOBJS = *.o *.bak
164
+
165
+ all: $(DLLIB)
166
+ static: $(STATIC_LIB)
167
+ .PHONY: all install static install-so install-rb
168
+ .PHONY: clean clean-so clean-static clean-rb
169
+
170
+ clean-static::
171
+ clean-rb-default::
172
+ clean-rb::
173
+ clean-so::
174
+ clean: clean-so clean-static clean-rb-default clean-rb
175
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
176
+
177
+ distclean-rb-default::
178
+ distclean-rb::
179
+ distclean-so::
180
+ distclean-static::
181
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
182
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
183
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
184
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
185
+
186
+ realclean: distclean
187
+ install: install-so install-rb
188
+
189
+ install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.-.sqlite_web_vfs.time
190
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
191
+ clean-static::
192
+ -$(Q)$(RM) $(STATIC_LIB)
193
+ install-rb: pre-install-rb do-install-rb install-rb-default
194
+ install-rb-default: pre-install-rb-default do-install-rb-default
195
+ pre-install-rb: Makefile
196
+ pre-install-rb-default: Makefile
197
+ do-install-rb:
198
+ do-install-rb-default:
199
+ pre-install-rb-default:
200
+ @$(NULLCMD)
201
+ $(TIMESTAMP_DIR)/.sitearchdir.-.sqlite_web_vfs.time:
202
+ $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
203
+ $(Q) $(TOUCH) $@
204
+
205
+ site-install: site-install-so site-install-rb
206
+ site-install-so: install-so
207
+ site-install-rb: install-rb
208
+
209
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
210
+
211
+ .cc.o:
212
+ $(ECHO) compiling $(<)
213
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
214
+
215
+ .cc.S:
216
+ $(ECHO) translating $(<)
217
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
218
+
219
+ .mm.o:
220
+ $(ECHO) compiling $(<)
221
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
222
+
223
+ .mm.S:
224
+ $(ECHO) translating $(<)
225
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
226
+
227
+ .cxx.o:
228
+ $(ECHO) compiling $(<)
229
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
230
+
231
+ .cxx.S:
232
+ $(ECHO) translating $(<)
233
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
234
+
235
+ .cpp.o:
236
+ $(ECHO) compiling $(<)
237
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
238
+
239
+ .cpp.S:
240
+ $(ECHO) translating $(<)
241
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
242
+
243
+ .c.o:
244
+ $(ECHO) compiling $(<)
245
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
246
+
247
+ .c.S:
248
+ $(ECHO) translating $(<)
249
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
250
+
251
+ .m.o:
252
+ $(ECHO) compiling $(<)
253
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
254
+
255
+ .m.S:
256
+ $(ECHO) translating $(<)
257
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
258
+
259
+ $(TARGET_SO): $(OBJS) Makefile
260
+ $(ECHO) linking shared-object sqlite_web_vfs/$(DLLIB)
261
+ -$(Q)$(RM) $(@)
262
+ $(Q) $(LDSHAREDXX) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
263
+ $(Q) $(POSTLINK)
264
+
265
+
266
+
267
+ $(OBJS): $(HDRS) $(ruby_headers)
Binary file
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'mkmf'
5
+ require 'fileutils'
6
+ require 'shellwords'
7
+ require 'net/http'
8
+ require 'uri'
9
+ # NOTE: mkmf will compile all .c/.cc files in this directory.
10
+
11
+ # Build settings
12
+ dir_config('sqlite3')
13
+
14
+ def darwin?
15
+ (/darwin/ =~ RUBY_PLATFORM) != nil
16
+ end
17
+
18
+ def linux?
19
+ (/linux/ =~ RUBY_PLATFORM) != nil
20
+ end
21
+
22
+ # Allow overriding via env or flags
23
+ sqlite_prefix = with_config('sqlite3-dir') || ENV.fetch('SQLITE3_DIR', nil)
24
+ if sqlite_prefix
25
+ inc = File.join(sqlite_prefix, 'include')
26
+ lib = File.join(sqlite_prefix, 'lib')
27
+ dir_config('sqlite3', inc, lib)
28
+ ENV['PKG_CONFIG_PATH'] = [File.join(lib, 'pkgconfig'), ENV.fetch('PKG_CONFIG_PATH', nil)].compact.join(':')
29
+ end
30
+
31
+ # HTTP implementation uses lazy-loaded libcurl when HTTP_LAZYCURL is defined.
32
+ # This avoids requiring libcurl at link time; on Linux we still need -ldl.
33
+ # Set required flags via mkmf CONFIG instead of globals
34
+ CONFIG['CPPFLAGS'] = [CONFIG['CPPFLAGS'], '-DHTTP_LAZYCURL'].compact.join(' ')
35
+ CONFIG['CXXFLAGS'] = [CONFIG['CXXFLAGS'], '-std=c++17', '-O2', '-DHTTP_LAZYCURL'].compact.join(' ')
36
+
37
+ have_library('dl') if linux?
38
+ have_library('pthread') if linux?
39
+
40
+ bundled = ENV['WEBVFS_FORCE_BUNDLED'] == '1'
41
+
42
+ if bundled
43
+ warn "\n==> WEBVFS_FORCE_BUNDLED=1 set: building against bundled SQLite amalgamation.\n " \
44
+ 'This is for advanced users and may not interoperate with other SQLite users in-process.'
45
+ # Download the amalgamation
46
+ require 'tmpdir'
47
+ require 'zlib'
48
+ require 'rubygems/package'
49
+
50
+ amalgamation_version = ENV['SQLITE_AMALGAMATION_VERSION'] || '3460000' # 3.46.0
51
+ base = "sqlite-amalgamation-#{amalgamation_version}"
52
+ url = "https://www.sqlite.org/2024/#{base}.zip"
53
+ dest_dir = File.expand_path('sqlite-amalgamation', __dir__)
54
+ FileUtils.mkdir_p(dest_dir)
55
+ zip_path = File.join(dest_dir, "#{base}.zip")
56
+ begin
57
+ uri = URI.parse(url)
58
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
59
+ http.request(Net::HTTP::Get.new(uri)) do |response|
60
+ abort "Failed to download SQLite amalgamation from #{url}: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
61
+ File.open(zip_path, 'wb') do |file|
62
+ response.read_body { |chunk| file.write(chunk) }
63
+ end
64
+ end
65
+ end
66
+ # unzip minimal without external tools
67
+ require 'zip'
68
+ rescue LoadError
69
+ # Fallback: try system unzip
70
+ end
71
+ if system('ruby', '-e', 'require "zip"; puts "ok"', out: File::NULL, err: File::NULL)
72
+ require 'zip'
73
+ Zip::File.open(zip_path) do |zip|
74
+ %w[sqlite3.c sqlite3.h sqlite3ext.h].each do |f|
75
+ e = zip.find_entry("#{base}/#{f}")
76
+ File.write(File.join(dest_dir, f), e.get_input_stream.read)
77
+ end
78
+ end
79
+ else
80
+ abort "Failed to extract SQLite amalgamation from #{zip_path}. Install 'rubyzip' or 'unzip'." unless system("unzip -o #{Shellwords.escape(zip_path)} -d #{Shellwords.escape(dest_dir)}")
81
+ %w[sqlite3.c sqlite3.h sqlite3ext.h].each do |f|
82
+ src = File.join(dest_dir, base, f)
83
+ FileUtils.cp(src, File.join(dest_dir, f))
84
+ end
85
+ end
86
+ # NOTE: Generate a tiny wrapper C file so mkmf picks up the amalgamation without globals
87
+ wrap_amalg = File.join(__dir__, '_wrap_sqlite3_amalgamation.c')
88
+ File.write(wrap_amalg, "#include \"sqlite-amalgamation/sqlite3.c\"\n") unless File.exist?(wrap_amalg)
89
+ # No need to link to system sqlite3 now
90
+ else
91
+ # Try pkg-config after probing Homebrew keg
92
+ begin
93
+ brew_sqlite = `brew --prefix sqlite 2>/dev/null`.strip
94
+ unless brew_sqlite.to_s.empty?
95
+ ENV['PKG_CONFIG_PATH'] = [File.join(brew_sqlite, 'lib/pkgconfig'), ENV.fetch('PKG_CONFIG_PATH', nil)].compact.join(':')
96
+ pkg_config('sqlite3') || true
97
+ end
98
+ rescue
99
+ end
100
+ # Try initial detection
101
+ sqlite_ok = have_header('sqlite3.h') && have_library('sqlite3', 'sqlite3_libversion_number')
102
+ # On macOS, also probe Homebrew keg paths if initial check failed or pkg-config lacked cflags
103
+ if !sqlite_ok && darwin?
104
+ begin
105
+ brew_sqlite = `brew --prefix sqlite 2>/dev/null`.strip
106
+ unless brew_sqlite.to_s.empty?
107
+ dir_config('sqlite3', File.join(brew_sqlite, 'include'), File.join(brew_sqlite, 'lib'))
108
+ ENV['PKG_CONFIG_PATH'] = [File.join(brew_sqlite, 'lib/pkgconfig'), ENV.fetch('PKG_CONFIG_PATH', nil)].compact.join(':')
109
+ pkg_config('sqlite3') || true
110
+ sqlite_ok = have_header('sqlite3.h') && have_library('sqlite3', 'sqlite3_libversion_number')
111
+ end
112
+ rescue
113
+ end
114
+ end
115
+ unless sqlite_ok
116
+ msg = <<~SQLITE_HELP
117
+
118
+ Could not find SQLite3 development headers and library.
119
+
120
+ Install SQLite and retry:
121
+ - macOS (Homebrew):
122
+ brew install sqlite
123
+ - Amazon Linux 2023:
124
+ sudo dnf install sqlite-devel
125
+
126
+ Or specify a custom path:
127
+ gem install sqlite_web_vfs -- --with-sqlite3-dir=/path/to/prefix
128
+
129
+ To force building with a bundled SQLite amalgamation (advanced):
130
+ WEBVFS_FORCE_BUNDLED=1 gem install sqlite_web_vfs
131
+ SQLITE_HELP
132
+ abort msg
133
+ end
134
+ end
135
+
136
+ # Ensure libcurl headers are available for compilation (lazy loaded at runtime)
137
+ curl_ok = have_header('curl/curl.h')
138
+ if !curl_ok && darwin?
139
+ begin
140
+ brew_curl = `brew --prefix curl 2>/dev/null`.strip
141
+ unless brew_curl.to_s.empty?
142
+ dir_config('curl', File.join(brew_curl, 'include'), File.join(brew_curl, 'lib'))
143
+ ENV['PKG_CONFIG_PATH'] = [File.join(brew_curl, 'lib/pkgconfig'), ENV.fetch('PKG_CONFIG_PATH', nil)].compact.join(':')
144
+ pkg_config('libcurl') || true
145
+ curl_ok = have_header('curl/curl.h')
146
+ end
147
+ rescue
148
+ end
149
+ end
150
+ unless curl_ok
151
+ msg = <<~CURL_HELP
152
+
153
+ Could not find libcurl development headers (curl/curl.h).
154
+
155
+ Install libcurl and retry:
156
+ - macOS (Homebrew):
157
+ brew install curl
158
+ - Amazon Linux 2023:
159
+ sudo dnf install libcurl-devel
160
+ CURL_HELP
161
+ abort msg
162
+ end
163
+
164
+ # On Linux, also link against libcurl to satisfy symbol resolution when loaders enforce RTLD_NOW.
165
+ have_library('curl', 'curl_easy_perform')
166
+
167
+ # Sources: C shim + vendored upstream C++ implementation
168
+ # NOTE: Generate a tiny wrapper to compile the upstream C++ file from this dir
169
+ wrap_web_vfs = File.join(__dir__, '_wrap_web_vfs.cc')
170
+ File.write(wrap_web_vfs, "#include \"upstream/web_vfs.cc\"\n") unless File.exist?(wrap_web_vfs)
171
+
172
+ # Ensure a C++ compiler is set and upstream headers are on include path
173
+ CONFIG['CXX'] ||= with_config('CXX', ENV['CXX'] || 'c++')
174
+ upstream_dir = File.expand_path('upstream', __dir__)
175
+ dir_config('upstream_headers', upstream_dir, nil)
176
+
177
+ create_makefile('sqlite_web_vfs/sqlite_web_vfs')
@@ -0,0 +1,5 @@
1
+ #ifndef SQLITE_WEB_VFS_FORWARD_READERWRITERQUEUE_H
2
+ #define SQLITE_WEB_VFS_FORWARD_READERWRITERQUEUE_H
3
+ #include "upstream/readerwriterqueue.h"
4
+ #endif
5
+
@@ -0,0 +1,16 @@
1
+ #include <ruby.h>
2
+ #include <sqlite3.h>
3
+
4
+ // Upstream extension init symbol from mlin/sqlite_web_vfs
5
+ extern int sqlite3_webvfs_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
6
+
7
+ // Provide the default SQLite extension entry point name so Database#load_extension (1-arg)
8
+ // can load this extension into an already-open connection.
9
+ int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) {
10
+ return sqlite3_webvfs_init(db, pzErrMsg, pApi);
11
+ }
12
+
13
+ void Init_sqlite_web_vfs(void) {
14
+ // Register the upstream VFS as an auto-extension so it's available to all connections
15
+ sqlite3_auto_extension((void (*)(void))sqlite3_webvfs_init);
16
+ }
Binary file