tebako 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/CMakeLists.txt +694 -0
  3. data/Gemfile +35 -0
  4. data/README.adoc +389 -0
  5. data/Rakefile +33 -0
  6. data/bin/console +15 -0
  7. data/bin/setup +8 -0
  8. data/cmake/copy_dir.cmake +29 -0
  9. data/cmake/def_tty_colours.cmake +19 -0
  10. data/common.env +6 -0
  11. data/exe/tebako +31 -0
  12. data/include/tebako/tebako-fs.h +40 -0
  13. data/include/tebako/tebako-main.h +40 -0
  14. data/lib/cli.rb +28 -0
  15. data/lib/tebako/cli.rb +137 -0
  16. data/lib/tebako/cli_helpers.rb +147 -0
  17. data/lib/tebako/error.rb +39 -0
  18. data/lib/tebako/packager/pass1.rb +155 -0
  19. data/lib/tebako/packager/pass2.rb +374 -0
  20. data/lib/tebako/packager.rb +210 -0
  21. data/lib/tebako/version.rb +30 -0
  22. data/resources/tebako-fs.cpp.in +37 -0
  23. data/resources/tebako-version.h.in +37 -0
  24. data/src/tebako-main.cpp +188 -0
  25. data/tebako.gemspec +63 -0
  26. data/tests/scripts/cross-tests.sh +34 -0
  27. data/tests/scripts/functional-tests.sh +335 -0
  28. data/tests/test-00/test.rb +4 -0
  29. data/tests/test-01/tebako-test-run.rb +5 -0
  30. data/tests/test-09/tebako-test-0.0.1.gem +0 -0
  31. data/tests/test-11/bin/tebako-test-run.rb +10 -0
  32. data/tests/test-11/lib/tebako-test.rb +20 -0
  33. data/tests/test-11/tebako-test.gemspec +15 -0
  34. data/tests/test-12/tebako-test-a.gemspec +15 -0
  35. data/tests/test-12/tebako-test-b.gemspec +15 -0
  36. data/tests/test-13/bin/tebako-test-run.rb +10 -0
  37. data/tests/test-13/lib/tebako-test.rb +20 -0
  38. data/tests/test-13/tebako-test.gemspec +15 -0
  39. data/tests/test-15/Gemfile +8 -0
  40. data/tests/test-15/Rakefile +4 -0
  41. data/tests/test-15/bin/tebako-test-run.rb +10 -0
  42. data/tests/test-15/lib/tebako/bundle/test/version.rb +9 -0
  43. data/tests/test-15/lib/tebako/bundle/test.rb +29 -0
  44. data/tests/test-15/tebako-bundle-test.gemspec +30 -0
  45. data/tests/test-16/Gemfile +8 -0
  46. data/tests/test-16/Rakefile +4 -0
  47. data/tests/test-16/bin/tebako-test-run.rb +10 -0
  48. data/tests/test-16/lib/tebako/bundle/test/version.rb +9 -0
  49. data/tests/test-16/lib/tebako/bundle/test.rb +29 -0
  50. data/tests/test-16/tebako-bundle-test.gemspec +24 -0
  51. data/tests/test-18/Gemfile +5 -0
  52. data/tests/test-18/tebako-test-run.rb +12 -0
  53. data/tests/test-19/Gemfile +6 -0
  54. data/tests/test-19/tebako-test-run.rb +11 -0
  55. data/tests-2/fixtures/gems-bundler/Gemfile +4 -0
  56. data/tests-2/fixtures/gems-bundler/gems-bundler.rb +34 -0
  57. data/tests-2/fixtures/gems-byebug/Gemfile +5 -0
  58. data/tests-2/fixtures/gems-byebug/gems-byebug.rb +31 -0
  59. data/tests-2/fixtures/gems-expressir/Gemfile +7 -0
  60. data/tests-2/fixtures/gems-expressir/gems-expressir.rb +33 -0
  61. data/tests-2/fixtures/gems-libmspack/Gemfile +5 -0
  62. data/tests-2/fixtures/gems-libmspack/gems-libmspack.rb +91 -0
  63. data/tests-2/fixtures/gems-sassc/Gemfile +6 -0
  64. data/tests-2/fixtures/gems-sassc/base_style/all.scss +1 -0
  65. data/tests-2/fixtures/gems-sassc/base_style/reset.scss +100 -0
  66. data/tests-2/fixtures/gems-sassc/gems-sassc.rb +129 -0
  67. data/tests-2/fixtures/gems-seven-zip/Gemfile +7 -0
  68. data/tests-2/fixtures/gems-seven-zip/gems-seven-zip.rb +53 -0
  69. data/tests-2/fixtures/launcher-coreincl/launcher-coreincl.rb +29 -0
  70. data/tests-2/fixtures/launcher-package/launcher-package.rb +29 -0
  71. data/tests-2/fixtures/launcher-pwd/launcher-pwd.rb +28 -0
  72. data/tests-2/fixtures/launcher-stdinredir/input.txt +1 -0
  73. data/tests-2/fixtures/launcher-stdinredir/launcher-stdinredir.rb +31 -0
  74. data/tests-2/fixtures/launcher-stdoutredir/launcher-stdoutredir.rb +28 -0
  75. data/tests-2/fixtures/patches-dir/level-1/level-2/file-1.txt +1 -0
  76. data/tests-2/fixtures/patches-dir/level-1/level-2/file-2.txt +1 -0
  77. data/tests-2/fixtures/patches-dir/level-1/level-2/file-3.txt +1 -0
  78. data/tests-2/fixtures/patches-dir/patches-dir.rb +154 -0
  79. data/tests-2/fixtures/patches-io-and-file/level-1/level-2/file-1.txt +1 -0
  80. data/tests-2/fixtures/patches-io-and-file/level-1/level-2/file-2.txt +2 -0
  81. data/tests-2/fixtures/patches-io-and-file/level-1/level-2/file-3.txt +1 -0
  82. data/tests-2/fixtures/patches-io-and-file/level-1/link-3 +1 -0
  83. data/tests-2/fixtures/patches-io-and-file/patches-io-and-file.rb +87 -0
  84. data/tests-2/fixtures/patches-main/patches-main.rb +6 -0
  85. data/tests-2/tebako-test.rb +312 -0
  86. metadata +170 -0
@@ -0,0 +1,374 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-2023 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of tebako
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
20
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ # POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ require "open3"
29
+
30
+ # Tebako - an executable packager
31
+ module Tebako
32
+ # Ruby patching definitions (pass2)
33
+ # rubocop:disable Metrics/ModuleLength
34
+ module Pass2
35
+ LINUX_GNU_LIBS = <<~SUBST
36
+ # -- Start of tebako patch --
37
+ MAINLIBS = -l:libtebako-fs.a -l:libdwarfs-wr.a -l:libdwarfs.a -l:libfolly.a -l:libfsst.a -l:libmetadata_thrift.a -l:libthrift_light.a -l:libxxhash.a \
38
+ -l:libfmt.a -l:libdouble-conversion.a -l:libglog.a -l:libgflags.a -l:libevent.a -l:libiberty.a -l:libacl.a -l:libssl.a -l:libcrypto.a -l:liblz4.a -l:libz.a \
39
+ -l:libzstd.a -l:libgdbm.a -l:libreadline.a -l:libtinfo.a -l:libffi.a -l:libncurses.a -l:libjemalloc.a -l:libunwind.a -l:libcrypt.a -l:libanl.a -l:liblzma.a \
40
+ -l:libboost_system.a -l:libstdc++.a -l:librt.a -ldl -lpthread
41
+ # -- End of tebako patch --
42
+ SUBST
43
+
44
+ LINUX_MUSL_LIBS = <<~SUBST
45
+ # -- Start of tebako patch --
46
+ MAINLIBS = -l:libtebako-fs.a -l:libdwarfs-wr.a -l:libdwarfs.a -l:libfolly.a -l:libfsst.a -l:libmetadata_thrift.a -l:libthrift_light.a -l:libxxhash.a \
47
+ -l:libfmt.a -l:libdouble-conversion.a -l:libglog.a -l:libgflags.a -l:libevent.a -l:libiberty.a -l:libacl.a -l:libssl.a -l:libcrypto.a -l:liblz4.a -l:libz.a \
48
+ -l:libzstd.a -l:libgdbm.a -l:libreadline.a -l:libffi.a -l:libncurses.a -l:libjemalloc.a -l:libunwind.a -l:libcrypt.a -l:liblzma.a \
49
+ -l:libboost_system.a -l:libstdc++.a -l:librt.a -ldl -lpthread
50
+ # -- End of tebako patch --
51
+ SUBST
52
+
53
+ MSYS_LIBS = <<~SUBST
54
+ # -- Start of tebako patch --
55
+ MAINLIBS = -l:libtebako-fs.a -l:libdwarfs-wr.a -l:libdwarfs.a -l:libfolly.a -l:libfsst.a -l:libmetadata_thrift.a -l:libthrift_light.a -l:libxxhash.a \
56
+ -l:libfmt.a -l:libdouble-conversion.a -l:libglog.a -l:libgflags.a -l:libevent.a -l:libssl.a -l:libcrypto.a -l:liblz4.a -l:libz.a \
57
+ -l:libzstd.a -l:libffi.a -l:libgdbm.a -l:libncurses.a -l:libjemalloc.a -l:libunwind.a -l:liblzma.a -l:libiberty.a \
58
+ -l:libstdc++.a -l:libdl.a -lole32 -loleaut32 -luuid
59
+ # -- End of tebako patch --
60
+ SUBST
61
+
62
+ TOOL_MKCONFIG_RB_PATCH = {
63
+ " if fast[name]" => <<~SUBST
64
+ # -- Start of tebako patch --
65
+ v_head_comp = " CONFIG[\\"prefix\\"] \#{eq} "
66
+ if v_head_comp == v[0...(v_head_comp.length)]
67
+ if win32
68
+ v = "\#{v[0...(v_head_comp.length)]}CONFIG[\\"RUBY_EXEC_PREFIX\\"] = '/__tebako_memfs__'
69
+ "
70
+ else
71
+ v = "\#{v[0...(v_head_comp.length)]}'/__tebako_memfs__'
72
+ "
73
+ end
74
+ end
75
+ v_head_comp = " CONFIG[\\"RUBY_EXEC_PREFIX\\"] \#{eq} "
76
+ if v_head_comp == v[0...(v_head_comp.length)]
77
+ v = "\#{v[0...(v_head_comp.length)]}'/__tebako_memfs__'
78
+ "
79
+ end
80
+ # -- End of tebako patch --
81
+ if fast[name]
82
+ SUBST
83
+ }.freeze
84
+
85
+ # Alpine-specific patches https://github.com/docker-library/ruby/blob/master/3.1/alpine3.15/Dockerfile
86
+ # -- Patch no. 1 --
87
+ # https://github.com/docker-library/ruby/issues/196
88
+ # https://bugs.ruby-lang.org/issues/14387#note-13 (patch source)
89
+ # https://bugs.ruby-lang.org/issues/14387#note-16
90
+ # ("Therefore ncopa's patch looks good for me in general." -- only breaks glibc which doesn't matter here)
91
+
92
+ # -- Patch no. 2 -- not needed: isnan, isinf are detected correctly by configure script
93
+ # the configure script does not detect isnan/isinf as macros
94
+ # export ac_cv_func_isnan=yes ac_cv_func_isinf=yes;
95
+
96
+ # -- Patch no. 3 --
97
+ # hack in "ENABLE_PATH_CHECK" disabling to suppress: "warning: Insecure world writable dir"
98
+ # Applied in CMakeLists.txt
99
+
100
+ LINUX_MUSL_THREAD_PTHREAD_PATCH = {
101
+ "#if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack)" => <<~SUBST
102
+ /* -- Start of tebako patch -- */
103
+ #if defined(__linux__) && !defined(__GLIBC__) && defined(HAVE_GETRLIMIT)
104
+ #ifndef PAGE_SIZE
105
+ #include <unistd.h>
106
+ #define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
107
+ #endif
108
+ static int
109
+ get_main_stack(void **addr, size_t *size)
110
+ {
111
+ size_t start, end, limit, prevend = 0;
112
+ struct rlimit r;
113
+ FILE *f;
114
+ char buf[PATH_MAX+80], s[8];
115
+ int n;
116
+ STACK_GROW_DIR_DETECTION;
117
+ f = fopen("/proc/self/maps", "re");
118
+ if (!f)
119
+ return -1;
120
+ n = 0;
121
+ while (fgets(buf, sizeof buf, f)) {
122
+ n = sscanf(buf, "%zx-%zx %*s %*s %*s %*s %7s", &start, &end, s);
123
+ if (n >= 2) {
124
+ if (n == 3 && strcmp(s, "[stack]") == 0)
125
+ break;
126
+ prevend = end;
127
+ }
128
+ n = 0;
129
+ }
130
+ fclose(f);
131
+ if (n == 0)
132
+ return -1;
133
+ limit = 100 << 20; /* 100MB stack limit */
134
+ if (getrlimit(RLIMIT_STACK, &r)==0 && r.rlim_cur < limit)
135
+ limit = r.rlim_cur & -PAGE_SIZE;
136
+ if (limit > end) limit = end;
137
+ if (prevend < end - limit) prevend = end - limit;
138
+ if (start > prevend) start = prevend;
139
+ *addr = IS_STACK_DIR_UPPER() ? (void *)start : (void *)end;
140
+ *size = end - start;
141
+ return 0;
142
+ }
143
+ #else
144
+ /* -- End of tebako patch -- */
145
+ SUBST
146
+ }.freeze
147
+
148
+ MAIN_C_PATCH = {
149
+ "int\nmain(int argc, char **argv)" =>
150
+ "#include <tebako/tebako-main.h>\n\nint\nmain(int argc, char **argv)",
151
+
152
+ " ruby_sysinit(&argc, &argv);" => <<~SUBST
153
+ ruby_sysinit(&argc, &argv);
154
+ /* -- Start of tebako patch -- */
155
+ if (tebako_main(&argc, &argv) != 0) {
156
+ return -1;
157
+ }
158
+ /* -- End of tebako patch -- */
159
+ SUBST
160
+ }.freeze
161
+
162
+ # Compensate ruby incorrect processing of (f)getattrlist returning ENOTSUP
163
+ # Note. We are not patching need_normalization function
164
+ # In this function (f)getattrlist failure with ENOTSUP is processed correctly
165
+
166
+ DIR_C_BASE_PATCH_ONE = <<~SUBST
167
+ #if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
168
+ /* tebako patch */ if (!within_tebako_memfs(path))
169
+ SUBST
170
+
171
+ DIR_C_BASE_PATCH_TWO = <<~SUBST
172
+ #if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
173
+ /* tebako patch */ if (!within_tebako_memfs(path)) plain = 1; else magical = 1;
174
+ SUBST
175
+
176
+ DIR_C_BASE_PATCH = {
177
+ "#if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT" => DIR_C_BASE_PATCH_ONE,
178
+ "#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME\n plain = 1;" => DIR_C_BASE_PATCH_TWO,
179
+ "if (is_case_sensitive(dirp, path) == 0)" =>
180
+ "if (is_case_sensitive(dirp, path) == 0 /* tebako patch */ && !within_tebako_memfs(path))",
181
+ "if ((*cur)->type == ALPHA) {" =>
182
+ "if ((*cur)->type == ALPHA /* tebako patch */ && !within_tebako_memfs(buf)) {",
183
+ "else if (e == EIO) {" =>
184
+ "else if (e == EIO /* tebako patch */ && !within_tebako_memfs(path)) {"
185
+ }.freeze
186
+
187
+ COMMON_MK_PATCH = {
188
+ "ext/extinit.c: $(srcdir)/template/extinit.c.tmpl $(PREP)" =>
189
+ "ext/extinit.c: $(srcdir)/template/extinit.c.tmpl $(PREP) $(EXTS_MK)"
190
+ }.freeze
191
+
192
+ C_FILES_TO_PATCH = [
193
+ ["file.c", "/* define system APIs */"],
194
+ ["io.c", "/* define system APIs */"],
195
+ ["util.c", "#ifndef S_ISDIR"],
196
+ ["dln.c", "static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;"]
197
+ ].freeze
198
+
199
+ TEMPLATE_MAKEFILE_IN_BASE_PATTERN_TWO_PRE_3_1 =
200
+ "\t\t$(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) " \
201
+ "$(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@"
202
+
203
+ TEMPLATE_MAKEFILE_IN_BASE_PATCH_TWO_PRE_3_1 =
204
+ "# -- Start of tebako patch --\n" \
205
+ "\t\t$(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) " \
206
+ "$(EXTOBJS) $(LIBRUBYARG_STATIC) $(LIBS) $(OUTFLAG)$@\n" \
207
+ "# -- End of tebako patch --"
208
+
209
+ TEMPLATE_MAKEFILE_IN_BASE_PATTERN_TWO =
210
+ "\t\t$(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) $(MAINOBJ) " \
211
+ "$(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@"
212
+
213
+ TEMPLATE_MAKEFILE_IN_BASE_PATCH_TWO =
214
+ "# -- Start of tebako patch --\n" \
215
+ "\t\t$(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) $(MAINOBJ) " \
216
+ "$(EXTOBJS) $(LIBRUBYARG_STATIC) $(LIBS) $(OUTFLAG)$@\n" \
217
+ "# -- End of tebako patch --"
218
+
219
+ C_FILE_SUBST = <<~SUBST
220
+ /* -- Start of tebako patch -- */
221
+ #ifndef NO_TEBAKO_INCLUDES
222
+ #include <tebako/tebako-config.h>
223
+ #include <tebako/tebako-defines.h>
224
+ #include <tebako/tebako-io-rb-w32.h>
225
+ #include <tebako/tebako-io.h>
226
+ #endif
227
+ /* -- End of tebako patch -- */
228
+ SUBST
229
+
230
+ MSYS_PATCHES = {
231
+ "ruby.c" => {
232
+ "#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))" =>
233
+ "#define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len)) /* tebako patched */",
234
+ "#define PREFIX_PATH() sopath" =>
235
+ "#define PREFIX_PATH() rubylib_path_new(tebako_mount_point(), " \
236
+ "strlen(tebako_mount_point())) /* tebako patched */",
237
+ '#include "mjit.h"' =>
238
+ "#include \"mjit.h\"\n" \
239
+ "/* -- Start of tebako patch -- */\n" \
240
+ "#include <tebako/tebako-main.h>\n" \
241
+ "/* -- End of tebako patch -- */"
242
+ },
243
+ "/win32/win32.c" => {
244
+ "#undef __STRICT_ANSI__" =>
245
+ "#undef __STRICT_ANSI__\n" \
246
+ "/* -- Start of tebako patch -- */\n" \
247
+ "#define NO_TEBAKO_INCLUDES\n" \
248
+ "/* -- End of tebako patch -- */"
249
+ },
250
+ "win32/dir.h" => {
251
+ "#define opendir(s) rb_w32_opendir((s))" => "#{C_FILE_SUBST}\n#define opendir(s) rb_w32_opendir((s))"
252
+ },
253
+ "file.c" => {
254
+ " wpath = mbstr_to_wstr(CP_UTF8, path, -1, &len);" =>
255
+ "/* -- Start of tebako patch -- */\n" \
256
+ "if (tebako_file_load_ok(path)) return 1;\n" \
257
+ "/* -- End of tebako patch -- */\n" \
258
+ "wpath = mbstr_to_wstr(CP_UTF8, path, -1, &len);",
259
+ '#include "win32/file.h' =>
260
+ "#include \"win32/file.h\"\n" \
261
+ "/* -- Start of tebako patch -- */\n" \
262
+ "#include <tebako/tebako-main.h>\n" \
263
+ "/* -- End of tebako patch -- */"
264
+ }
265
+
266
+ }.freeze
267
+
268
+ # rubocop:disable Style/WordArray
269
+ DARWIN_BREW_LIBS = [
270
+ ["openssl@1.1", "ssl"], ["openssl@1.1", "crypto"],
271
+ ["zlib", "z"], ["gdbm", "gdbm"],
272
+ ["readline", "readline"], ["libffi", "ffi"],
273
+ ["ncurses", "ncurses"], ["fmt", "fmt"],
274
+ ["lz4", "lz4"], ["xz", "lzma"],
275
+ ["double-conversion", "double-conversion"]
276
+ ].freeze
277
+
278
+ DARWIN_DEP_LIBS = ["glog", "gflags"].freeze
279
+ # rubocop:enable Style/WordArray
280
+
281
+ class << self
282
+ # rubocop:disable Metrics/MethodLength
283
+ def get_patch_map(ostype, deps_lib_dir, ruby_ver)
284
+ dir_c_patch = patch_c_file(ostype =~ /msys/ ? "/* define system APIs */" : "#ifdef HAVE_GETATTRLIST")
285
+ dir_c_patch.merge!(DIR_C_BASE_PATCH)
286
+
287
+ patch_map = {
288
+ "template/Makefile.in" => template_makefile_in_patch(ostype, deps_lib_dir, ruby_ver),
289
+ "main.c" => MAIN_C_PATCH,
290
+ "tool/mkconfig.rb" => TOOL_MKCONFIG_RB_PATCH,
291
+ "dir.c" => dir_c_patch
292
+ }
293
+
294
+ C_FILES_TO_PATCH.each { |patch| patch_map.store(patch[0], patch_c_file(patch[1])) }
295
+ patch_map.store("thread_pthread.c", LINUX_MUSL_THREAD_PTHREAD_PATCH) if ostype =~ /linux-musl/
296
+ patch_map.merge!(MSYS_PATCHES) if ostype =~ /msys/
297
+
298
+ patch_map.store("common.mk", COMMON_MK_PATCH) if ruby_ver[0] == "3"
299
+
300
+ patch_map
301
+ end
302
+ # rubocop:enable Metrics/MethodLength
303
+
304
+ private
305
+
306
+ def get_prefix(package)
307
+ out, st = Open3.capture2("brew --prefix #{package}")
308
+ raise TebakoError, "brew --prefix #{package} failed with code #{st.exitstatus}" unless st.exitstatus.zero?
309
+
310
+ out
311
+ end
312
+
313
+ def darwin_libs(deps_lib_dir)
314
+ libs = String.new
315
+ DARWIN_BREW_LIBS.each do |lib|
316
+ libs << get_prefix(lib[0]).chop << "/lib/lib#{lib[1]}.a "
317
+ end
318
+ DARWIN_DEP_LIBS.each do |lib|
319
+ libs << deps_lib_dir << "/lib#{lib}.a "
320
+ end
321
+ <<~SUBST
322
+ # -- Start of tebako patch --
323
+ MAINLIBS = -ltebako-fs -ldwarfs-wr -ldwarfs -lfolly -lfsst -lmetadata_thrift -lthrift_light -lxxhash \
324
+ -lzstd #{libs} -ljemalloc -lc++
325
+ # -- End of tebako patch --
326
+ SUBST
327
+ end
328
+
329
+ # rubocop:disable Metrics/MethodLength
330
+ def mlibs(ostype, deps_lib_dir)
331
+ case ostype
332
+ when /linux-gnu/
333
+ LINUX_GNU_LIBS
334
+ when /linux-musl/
335
+ LINUX_MUSL_LIBS
336
+ when /darwin/
337
+ darwin_libs(deps_lib_dir)
338
+ when /msys/
339
+ MSYS_LIBS
340
+ else
341
+ raise TebakoError, "Unknown ostype #{ostype}"
342
+ end
343
+ end
344
+ # rubocop:enable Metrics/MethodLength
345
+
346
+ def patch_c_file(pattern)
347
+ {
348
+ pattern => "#{C_FILE_SUBST}\n#{pattern}"
349
+ }
350
+ end
351
+
352
+ def template_makefile_in_patch(ostype, deps_lib_dir, ruby_ver)
353
+ base_patch = {
354
+ "MAINLIBS = @MAINLIBS@" => mlibs(ostype, deps_lib_dir),
355
+ "LIBS = @LIBS@ $(EXTLIBS)" => <<~SUBST
356
+ # -- Start of tebako patch --
357
+ LIBS = $(MAINLIBS) @LIBS@
358
+ # -- End of tebako patch --
359
+ SUBST
360
+ }
361
+ base_patch.merge!(template_makefile_in_patch_two(ruby_ver))
362
+ end
363
+
364
+ def template_makefile_in_patch_two(ruby_ver)
365
+ if ruby_ver[0] == "3" && ruby_ver[2] != "0"
366
+ { TEMPLATE_MAKEFILE_IN_BASE_PATTERN_TWO => TEMPLATE_MAKEFILE_IN_BASE_PATCH_TWO }
367
+ else
368
+ { TEMPLATE_MAKEFILE_IN_BASE_PATTERN_TWO_PRE_3_1 => TEMPLATE_MAKEFILE_IN_BASE_PATCH_TWO_PRE_3_1 }
369
+ end
370
+ end
371
+ end
372
+ end
373
+ # rubocop:enable Metrics/ModuleLength
374
+ end
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright (c) 2021-2023 [Ribose Inc](https://www.ribose.com).
5
+ # All rights reserved.
6
+ # This file is a part of tebako
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions
10
+ # are met:
11
+ # 1. Redistributions of source code must retain the above copyright
12
+ # notice, this list of conditions and the following disclaimer.
13
+ # 2. Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
21
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require "fileutils"
30
+
31
+ require_relative "error"
32
+ require_relative "packager/pass1"
33
+ require_relative "packager/pass2"
34
+
35
+ # Tebako - an executable packager
36
+ module Tebako
37
+ # Tebako packaging support (internal)
38
+ module Packager
39
+ FILES_TO_RESTORE = [
40
+ "main.c", "dir.c", "dln.c",
41
+ "file.c", "io.c", "tool/mkconfig.rb"
42
+ ].freeze
43
+
44
+ FILES_TO_RESTORE_MSYS = [
45
+ "ruby.c", "win32/win32.c",
46
+ "win32/file.c", "win32/dir.h"
47
+ ].freeze
48
+
49
+ FILES_TO_RESTORE_MUSL = [
50
+ "thread_pthread.c"
51
+ ].freeze
52
+
53
+ class << self
54
+ # Pass1
55
+ # Executed before Ruby build, patching ensures that Ruby itself is linked statically
56
+ def pass1(ostype, ruby_source_dir, mount_point, src_dir, ruby_ver)
57
+ puts "-- Running pass1 script"
58
+
59
+ recreate(src_dir)
60
+ do_patch(Pass1.get_patch_map(ostype, mount_point, ruby_ver), ruby_source_dir)
61
+
62
+ # Roll back pass2 patches
63
+ # Just in case we are recovering after some error
64
+ restore_and_save_files(FILES_TO_RESTORE, ruby_source_dir)
65
+ restore_and_save_files(FILES_TO_RESTORE_MUSL, ruby_source_dir) if ostype =~ /linux-musl/
66
+ restore_and_save_files(FILES_TO_RESTORE_MSYS, ruby_source_dir) if ostype =~ /msys/
67
+ end
68
+
69
+ # Pass2
70
+ # Creates packaging environment, patching ensures that tebako package is linked statically
71
+ def pass2(ostype, ruby_source_dir, deps_lib_dir, ruby_ver)
72
+ puts "-- Running pass2 script"
73
+
74
+ do_patch(Pass2.get_patch_map(ostype, deps_lib_dir, ruby_ver), ruby_source_dir)
75
+ end
76
+
77
+ # Stash
78
+ # Saves pristine Ruby environment that is used to deploy applications for packaging
79
+ def stash(src_dir, stash_dir)
80
+ puts "-- Running stash script"
81
+ # .... this code snippet is executed 'outdside' of Ruby scripts
82
+ # shall be reconsidered
83
+ # FileUtils.cd ruby_source_dir do
84
+ # puts " ... creating pristine ruby environment at #{src_dir} [patience, it will take some time]"
85
+ # out, st = Open3.capture2e("cmake", "-E", "chdir", ruby_source_dir, "make", "install")
86
+ # print out if st.exitstatus != 0 || verbose
87
+ # raise TebakoError.new("stash [make install] failed with code #{st.exitstatus}") if st.exitstatus != 0
88
+ # end
89
+
90
+ puts " ... saving pristine ruby environment to #{stash_dir}"
91
+ recreate(stash_dir)
92
+ FileUtils.cp_r "#{src_dir}/.", stash_dir
93
+ end
94
+
95
+ # Deploy
96
+ # To be extended
97
+ # Now it just recreates Ruby prostine environment from stash
98
+ def deploy(stash_dir, src_dir, pre_dir, bin_dir)
99
+ puts "-- Running deploy script"
100
+
101
+ puts " ... creating packaging environment at #{src_dir}"
102
+ recreate([src_dir, pre_dir, bin_dir])
103
+ FileUtils.cp_r "#{stash_dir}/.", src_dir
104
+ end
105
+
106
+ private
107
+
108
+ def recreate(dirname)
109
+ FileUtils.rm_rf(dirname, noop: nil, verbose: nil, secure: true)
110
+ FileUtils.mkdir(dirname)
111
+ end
112
+
113
+ def restore_and_save(fname)
114
+ raise TebakoError, "Could not save #{fname} because it does not exist." unless File.exist?(fname)
115
+
116
+ old_fname = "#{fname}.old"
117
+ if File.exist?(old_fname)
118
+ FileUtils.rm_f(fname)
119
+ File.rename(old_fname, fname)
120
+ end
121
+ FileUtils.cp(fname, old_fname)
122
+ end
123
+
124
+ def restore_and_save_files(files, ruby_source_dir)
125
+ files.each do |fname|
126
+ restore_and_save "#{ruby_source_dir}/#{fname}"
127
+ end
128
+ end
129
+
130
+ def patch_file(fname, mapping)
131
+ raise TebakoError, "Could not patch #{fname} because it does not exist." unless File.exist?(fname)
132
+
133
+ puts " ... patching #{fname}"
134
+ restore_and_save(fname)
135
+ contents = File.read(fname)
136
+ mapping.each { |pattern, subst| contents.sub!(pattern, subst) }
137
+ File.open(fname, "w") { |file| file << contents }
138
+ end
139
+
140
+ def do_patch(patch_map, root)
141
+ patch_map.each { |fname, mapping| patch_file("#{root}/#{fname}", mapping) }
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ begin
148
+ unless ARGV.length.positive?
149
+ raise Tebako::TebakoError, "Tebako script needs at least 1 arguments (command), none has been provided."
150
+ end
151
+
152
+ case ARGV[0]
153
+ when "pass1"
154
+ # ARGV[0] -- command
155
+ # ARGV[1] -- OSTYPE
156
+ # ARGV[2] -- RUBY_SOURCE_DIR
157
+ # ARGV[3] -- FS_MOUNT_POINT
158
+ # ARGV[4] -- DATA_SRC_DIR
159
+ # ARGV[5] -- RUBY_VER
160
+ unless ARGV.length == 6
161
+ raise Tebako::TebakoError,
162
+ "pass1 script expects 6 arguments, #{ARGV.length} has been provided."
163
+ end
164
+
165
+ Tebako::Packager.pass1(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5])
166
+ when "stash"
167
+ # ARGV[0] -- command
168
+ # ARGV[1] -- DATA_SRC_DIR
169
+ # ARGV[2] -- RUBY_STASH_DIR
170
+ unless ARGV.length == 3
171
+ raise Tebako::TebakoError,
172
+ "stash script expects 3 arguments, #{ARGV.length} has been provided."
173
+ end
174
+
175
+ Tebako::Packager.stash(ARGV[1], ARGV[2])
176
+ when "pass2"
177
+ # ARGV[0] -- command
178
+ # ARGV[1] -- OSTYPE
179
+ # ARGV[2] -- RUBY_SOURCE_DIR
180
+ # ARGV[3] -- DEPS_LIB_DIR
181
+ # ARGV[4] -- DATA_SRC_DIR
182
+ # ARGV[5] -- RUBY_STASH_DIR
183
+ # ARGV[6] -- RUBY_VER
184
+ unless ARGV.length == 7
185
+ raise Tebako::TebakoError,
186
+ "pass1 script expects 7 arguments, #{ARGV.length} has been provided."
187
+ end
188
+
189
+ Tebako::Packager.stash(ARGV[4], ARGV[5])
190
+ Tebako::Packager.pass2(ARGV[1], ARGV[2], ARGV[3], ARGV[6])
191
+ when "deploy"
192
+ # ARGV[0] -- command
193
+ # ARGV[1] -- FS_STASH_DIR
194
+ # ARGV[2] -- DATA_SRC_DIR
195
+ # ARGV[3] -- DATA_PRE_DIR
196
+ # ARGV[4] -- DATA_BIN_DIR
197
+ unless ARGV.length == 5
198
+ raise Tebako::TebakoError,
199
+ "deploy script expects 5 arguments, #{ARGV.length} has been provided."
200
+ end
201
+ Tebako::Packager.deploy(ARGV[1], ARGV[2], ARGV[3], ARGV[4])
202
+ else
203
+ raise Tebako::TebakoError, "Tebako script cannot process #{ARGV[0]} command"
204
+ end
205
+ rescue Tebako::TebakoError => e
206
+ puts "Tebako script failed: #{e.message} [#{e.error_code}]"
207
+ exit(e.error_code)
208
+ end
209
+
210
+ exit(0)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2023 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of tebako
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
20
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ # POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ module Tebako
29
+ VERSION = "0.5.0"
30
+ end
@@ -0,0 +1,37 @@
1
+ /**
2
+ *
3
+ * Copyright (c) 2021-2022 [Ribose Inc](https://www.ribose.com).
4
+ * All rights reserved.
5
+ * This file is a part of tebako
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ * 1. Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * 2. Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
20
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ */
29
+
30
+ #include <incbin/incbin.h>
31
+
32
+ namespace tebako {
33
+ const char * fs_log_level = "@LOG_LEVEL@";
34
+ const char * fs_mount_point = "@FS_MOUNT_POINT@";
35
+ const char * fs_entry_point = "@FS_ENTRY_POINT@";
36
+ INCBIN(fs, "@DATA_BIN_FILE@");
37
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ *
3
+ * Copyright (c) 2021, [Ribose Inc](https://www.ribose.com).
4
+ * All rights reserved.
5
+ * This file is a part of tebako
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ * 1. Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * 2. Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
20
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ */
29
+
30
+
31
+ #pragma once
32
+
33
+ const unsigned int tebako_version_major = @PROJECT_VERSION_MAJOR@;
34
+ const unsigned int tebako_version_minor = @PROJECT_VERSION_MINOR@;
35
+ const unsigned int tebako_version_teeny = @PROJECT_VERSION_PATCH@;
36
+
37
+