rbe-tebako 0.15.0

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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +4 -0
  3. data/Brewfile +23 -0
  4. data/CMakeLists.txt +464 -0
  5. data/CODE_OF_CONDUCT.adoc +128 -0
  6. data/CONTRIBUTING.adoc +294 -0
  7. data/Gemfile +31 -0
  8. data/INSTALLATION.adoc +233 -0
  9. data/LICENSE.md +33 -0
  10. data/README.adoc +1363 -0
  11. data/Rakefile +35 -0
  12. data/bin/console +15 -0
  13. data/bin/setup +8 -0
  14. data/cmake/copy_dir.cmake +29 -0
  15. data/common.env +5 -0
  16. data/exe/rbe-tebako +32 -0
  17. data/exe/rbe-tebako-packager +77 -0
  18. data/include/tebako/tebako-fs.h +43 -0
  19. data/include/tebako/tebako-main.h +42 -0
  20. data/include/tebako/tebako-prism.h +51 -0
  21. data/lib/rbe-tebako.rb +6 -0
  22. data/lib/tebako/build_helpers.rb +77 -0
  23. data/lib/tebako/cache_manager.rb +112 -0
  24. data/lib/tebako/cli.rb +220 -0
  25. data/lib/tebako/cli_helpers.rb +165 -0
  26. data/lib/tebako/codegen.rb +252 -0
  27. data/lib/tebako/deploy_helper.rb +258 -0
  28. data/lib/tebako/error.rb +70 -0
  29. data/lib/tebako/options_manager.rb +338 -0
  30. data/lib/tebako/package_descriptor.rb +143 -0
  31. data/lib/tebako/packager/pass1_patch.rb +266 -0
  32. data/lib/tebako/packager/pass1a_patch.rb +55 -0
  33. data/lib/tebako/packager/pass2_patch.rb +140 -0
  34. data/lib/tebako/packager/pass2_patch_crt.rb +46 -0
  35. data/lib/tebako/packager/pass2msys_patch.rb +190 -0
  36. data/lib/tebako/packager/patch.rb +54 -0
  37. data/lib/tebako/packager/patch_buildsystem.rb +124 -0
  38. data/lib/tebako/packager/patch_helpers.rb +109 -0
  39. data/lib/tebako/packager/patch_libraries.rb +188 -0
  40. data/lib/tebako/packager/patch_literals.rb +275 -0
  41. data/lib/tebako/packager/patch_main.rb +93 -0
  42. data/lib/tebako/packager/rubygems_patch.rb +83 -0
  43. data/lib/tebako/packager.rb +210 -0
  44. data/lib/tebako/packager_lite.rb +78 -0
  45. data/lib/tebako/ruby_builder.rb +71 -0
  46. data/lib/tebako/ruby_version.rb +206 -0
  47. data/lib/tebako/scenario_manager.rb +251 -0
  48. data/lib/tebako/stripper.rb +135 -0
  49. data/lib/tebako/version.rb +30 -0
  50. data/lib/tebako.rb +34 -0
  51. data/src/tebako-main.cpp +168 -0
  52. data/tools/.gitattributes +4 -0
  53. data/tools/.github/workflows/build-containers.yml +190 -0
  54. data/tools/.github/workflows/lint.yml +41 -0
  55. data/tools/.github/workflows/test.yml +331 -0
  56. data/tools/.gitignore +1 -0
  57. data/tools/README.md +49 -0
  58. data/tools/ci-scripts/arm-brew-install.sh +43 -0
  59. data/tools/ci-scripts/arm-brew-setup.sh +33 -0
  60. data/tools/ci-scripts/level-up.sh +35 -0
  61. data/tools/ci-scripts/patch-fbthrift.sh +94 -0
  62. data/tools/ci-scripts/patch-folly.sh +551 -0
  63. data/tools/ci-scripts/patch-glog.sh +57 -0
  64. data/tools/ci-scripts/patch-zstd.sh +57 -0
  65. data/tools/ci-scripts/tools.sh +63 -0
  66. data/tools/ci-scripts/x86-brew-install.sh +43 -0
  67. data/tools/ci-scripts/x86-brew-setup.sh +33 -0
  68. data/tools/cmake-scripts/def-external-project.cmake +96 -0
  69. data/tools/cmake-scripts/macos-environment.cmake +91 -0
  70. data/tools/cmake-scripts/msys-environment.cmake +78 -0
  71. data/tools/cmake-scripts/setup-libarchive.cmake +93 -0
  72. data/tools/cmake-scripts/setup-libfmt.cmake +61 -0
  73. data/tools/cmake-scripts/setup-libhowardhinnerdate.cmake +55 -0
  74. data/tools/cmake-scripts/setup-libutfcpp.cmake +56 -0
  75. data/tools/cmake-scripts/version.cmake +162 -0
  76. data/tools/docker/alpine-3.17-dev.Dockerfile +49 -0
  77. data/tools/docker/tools/tools.sh +66 -0
  78. data/tools/docker/ubuntu-20.04-dev.Dockerfile +51 -0
  79. data/tools/dwarfs-test-helper/CMakeLists.txt +34 -0
  80. data/tools/include/pro-statvfs.h +57 -0
  81. data/tools/tests/cmake/CMakeLists.txt +81 -0
  82. data/tools/tests/setup-libfmt/CMakeLists.txt +35 -0
  83. data/tools/tests/setup-libhowardhinnerdate/CMakeLists.txt +35 -0
  84. data/tools/tests/setup-librachive/CMakeLists.txt +35 -0
  85. data/tools/tests/setup-libutfcpp/CMakeLists.txt +36 -0
  86. data/tools/tests/setup-openssl/CMakeLists.txt +36 -0
  87. metadata +312 -0
@@ -0,0 +1,275 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2023-2025 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of the Tebako project.
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
+ # Tebako - an executable packager
29
+ module Tebako
30
+ module Packager
31
+ # Ruby patching literals (pass2)
32
+ module PatchLiterals
33
+ TOOL_MKCONFIG_RB_SUBST = <<~SUBST
34
+ # -- Start of tebako patch --
35
+ v_head_comp = " CONFIG[\\"prefix\\"] \#{eq} "
36
+ if v_head_comp == v[0...(v_head_comp.length)]
37
+ v = "\#{v[0...(v_head_comp.length)]}'/__tebako_memfs__'
38
+ "
39
+ end
40
+ v_head_comp = " CONFIG[\\"RUBY_EXEC_PREFIX\\"] \#{eq} "
41
+ if v_head_comp == v[0...(v_head_comp.length)]
42
+ v = "\#{v[0...(v_head_comp.length)]}'/__tebako_memfs__'
43
+ "
44
+ end
45
+ # -- End of tebako patch --
46
+ if fast[name]
47
+ SUBST
48
+
49
+ TOOL_MKCONFIG_RB_SUBST_MSYS = <<~SUBST
50
+ # -- Start of tebako patch --
51
+ v_head_comp = " CONFIG[\\"prefix\\"] \#{eq} "
52
+ if v_head_comp == v[0...(v_head_comp.length)]
53
+ v = "\#{v[0...(v_head_comp.length)]}CONFIG[\\"RUBY_EXEC_PREFIX\\"] = 'A:/__tebako_memfs__'
54
+ "
55
+ end
56
+ v_head_comp = " CONFIG[\\"RUBY_EXEC_PREFIX\\"] \#{eq} "
57
+ if v_head_comp == v[0...(v_head_comp.length)]
58
+ v = "\#{v[0...(v_head_comp.length)]}'A:/__tebako_memfs__'
59
+ "
60
+ end
61
+ # -- End of tebako patch --
62
+ if fast[name]
63
+ SUBST
64
+
65
+ # Alpine-specific patches https://github.com/docker-library/ruby/blob/master/3.1/alpine3.15/Dockerfile
66
+ # -- Patch no. 1 --
67
+ # https://github.com/docker-library/ruby/issues/196
68
+ # https://bugs.ruby-lang.org/issues/14387#note-13 (patch source)
69
+ # https://bugs.ruby-lang.org/issues/14387#note-16
70
+ # ("Therefore ncopa's patch looks good for me in general." -- only breaks glibc which doesn't matter here)
71
+
72
+ # -- Patch no. 2 -- not needed: isnan, isinf are detected correctly by configure script
73
+ # the configure script does not detect isnan/isinf as macros
74
+ # export ac_cv_func_isnan=yes ac_cv_func_isinf=yes;
75
+
76
+ # -- Patch no. 3 --
77
+ # hack in "ENABLE_PATH_CHECK" disabling to suppress: "warning: Insecure world writable dir"
78
+ # Applied in CMakeLists.txt
79
+
80
+ LINUX_MUSL_THREAD_PTHREAD_PATCH = {
81
+ "#if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack)" => <<~SUBST
82
+ /* -- Start of tebako patch -- */
83
+ #if defined(__linux__) && !defined(__GLIBC__) && defined(HAVE_GETRLIMIT)
84
+ #ifndef PAGE_SIZE
85
+ #include <unistd.h>
86
+ #define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
87
+ #endif
88
+ static int
89
+ get_main_stack(void **addr, size_t *size)
90
+ {
91
+ size_t start, end, limit, prevend = 0;
92
+ struct rlimit r;
93
+ FILE *f;
94
+ char buf[PATH_MAX+80], s[8];
95
+ int n;
96
+ STACK_GROW_DIR_DETECTION;
97
+ f = fopen("/proc/self/maps", "re");
98
+ if (!f)
99
+ return -1;
100
+ n = 0;
101
+ while (fgets(buf, sizeof buf, f)) {
102
+ n = sscanf(buf, "%zx-%zx %*s %*s %*s %*s %7s", &start, &end, s);
103
+ if (n >= 2) {
104
+ if (n == 3 && strcmp(s, "[stack]") == 0)
105
+ break;
106
+ prevend = end;
107
+ }
108
+ n = 0;
109
+ }
110
+ fclose(f);
111
+ if (n == 0)
112
+ return -1;
113
+ limit = 100 << 20; /* 100MB stack limit */
114
+ if (getrlimit(RLIMIT_STACK, &r)==0 && r.rlim_cur < limit)
115
+ limit = r.rlim_cur & -PAGE_SIZE;
116
+ if (limit > end) limit = end;
117
+ if (prevend < end - limit) prevend = end - limit;
118
+ if (start > prevend) start = prevend;
119
+ *addr = IS_STACK_DIR_UPPER() ? (void *)start : (void *)end;
120
+ *size = end - start;
121
+ return 0;
122
+ }
123
+ #else
124
+ /* -- End of tebako patch -- */
125
+ SUBST
126
+ }.freeze
127
+
128
+ # Compensate ruby incorrect processing of (f)getattrlist returning ENOTSUP
129
+ # Note. We are not patching need_normalization function
130
+ # In this function (f)getattrlist failure with ENOTSUP is processed correctly
131
+
132
+ DIR_C_BASE_PATCH_ONE = <<~SUBST
133
+ #if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
134
+ /* tebako patch */ if (!within_tebako_memfs(path))
135
+ SUBST
136
+
137
+ DIR_C_BASE_PATCH_TWO = <<~SUBST
138
+ #if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
139
+ /* tebako patch */ if (!within_tebako_memfs(path)) plain = 1; else magical = 1;
140
+ SUBST
141
+
142
+ DIR_C_BASE_PATCH = {
143
+ "#if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT" => DIR_C_BASE_PATCH_ONE,
144
+ "#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME\n plain = 1;" => DIR_C_BASE_PATCH_TWO,
145
+ "if (is_case_sensitive(dirp, path) == 0)" =>
146
+ "if (is_case_sensitive(dirp, path) == 0 /* tebako patch */ && !within_tebako_memfs(path))",
147
+ "if ((*cur)->type == ALPHA) {" =>
148
+ "if ((*cur)->type == ALPHA /* tebako patch */ && !within_tebako_memfs(buf)) {",
149
+ "else if (e == EIO) {" =>
150
+ "else if (e == EIO /* tebako patch */ && !within_tebako_memfs(path)) {"
151
+ }.freeze
152
+
153
+ DLN_C_PRE34_PATCH_PATTERN = "static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;"
154
+
155
+ DLN_C_PATCH_PATTERN = "#define init_funcname(buf, file) build_funcname(FUNCNAME_PREFIX, buf, file)"
156
+
157
+ DLN_C_MSYS_PATCH_PRE32 = {
158
+ " winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);" => <<~SUBST
159
+ /* -- Start of tebako patch -- */
160
+ char *f = NULL;
161
+ winfile = NULL;
162
+ if (file && within_tebako_memfs(file)) {
163
+ f = tebako_dlmap2file(file);
164
+ if (f) {
165
+ winfile = rb_w32_mbstr_to_wstr(CP_UTF8, f, -1, NULL);
166
+ free(f);
167
+ }
168
+ else {
169
+ goto failed;
170
+ }
171
+ }
172
+ else {
173
+ winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
174
+ }
175
+ /* -- End of tebako patch -- */
176
+ SUBST
177
+ }.freeze
178
+
179
+ DLN_C_MSYS_PATCH = {
180
+ " WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);" => <<~SUBST
181
+ /* -- Start of tebako patch -- */
182
+ char *f = NULL;
183
+ WCHAR *winfile = NULL;
184
+ if (file && within_tebako_memfs(file)) {
185
+ f = tebako_dlmap2file(file);
186
+ if (f) {
187
+ winfile = rb_w32_mbstr_to_wstr(CP_UTF8, f, -1, NULL);
188
+ free(f);
189
+ }
190
+ else {
191
+ goto failed;
192
+ }
193
+ }
194
+ else {
195
+ winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
196
+ }
197
+ /* -- End of tebako patch -- */
198
+ SUBST
199
+ }.freeze
200
+
201
+ C_FILE_SUBST = <<~SUBST
202
+ /* -- Start of tebako patch -- */
203
+ #include <tebako/tebako-config.h>
204
+ #include <tebako/tebako-defines.h>
205
+ #include <tebako/tebako-io.h>
206
+ /* -- End of tebako patch -- */
207
+ SUBST
208
+
209
+ C_FILE_SUBST_LESS = <<~SUBST
210
+ /* -- Start of tebako patch -- */
211
+ #include <tebako/tebako-config.h>
212
+ #include <tebako/tebako-io.h>
213
+ /* -- End of tebako patch -- */
214
+ SUBST
215
+
216
+ IO_C_SUBST = <<~SUBST
217
+ /* -- Start of tebako patch -- */
218
+ if (is_tebako_file_descriptor(fd)) return;
219
+ /* -- End of tebako patch -- */
220
+ flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
221
+ SUBST
222
+
223
+ FILE_C_MSYS_SUBST = <<~SUBST
224
+ /* -- Start of tebako patch -- */
225
+ if (is_tebako_file_descriptor((fptr)->fd)) return ENOTSUP;
226
+ /* -- End of tebako patch -- */
227
+ while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
228
+ SUBST
229
+
230
+ FILE_C_MSYS_PATCH = {
231
+ "while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {" => FILE_C_MSYS_SUBST
232
+ }.freeze
233
+
234
+ LINUX_PATCHES = {
235
+ "ext/extmk.rb" => {
236
+ "mf.macro \"EXTLIBS\", $extlibs" => "# mf.macro \"EXTLIBS\", $extlibs tebako patched"
237
+ }
238
+ }.freeze
239
+
240
+ PRISM_PATTERN_1 = "pm_string_init_result_t init_result = pm_read_file(&result->input, RSTRING_PTR(filepath));"
241
+
242
+ PRISM_SUBST_1 = <<~SUBST
243
+ /* -- Start of tebako patch -- */
244
+ pm_string_init_result_t init_result;
245
+ if (within_tebako_memfs(RSTRING_PTR(filepath)))
246
+ {
247
+ init_result = tebako_string_file_init(&result->input, RSTRING_PTR(filepath));
248
+ }
249
+ else
250
+ {
251
+ init_result = pm_read_file(&result->input, RSTRING_PTR(filepath));
252
+ }
253
+ /* -- End of tebako patch -- */
254
+ SUBST
255
+
256
+ PRISM_PATTERN_2 = "#include \"prism.h\""
257
+ PRISM_SUBST_2 = <<~SUBST
258
+ #{PRISM_PATTERN_2}
259
+
260
+ /* -- Start of tebako patch -- */
261
+ #include <tebako/tebako-config.h>
262
+ #include <tebako/tebako-defines.h>
263
+ #include <tebako/tebako-io.h>
264
+ #include <tebako/tebako-prism.h>
265
+ /* -- End of tebako patch -- */
266
+
267
+ SUBST
268
+
269
+ PRISM_PATCHES = {
270
+ PRISM_PATTERN_1 => PRISM_SUBST_1,
271
+ PRISM_PATTERN_2 => PRISM_SUBST_2
272
+ }.freeze
273
+ end
274
+ end
275
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2023-2025 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of the Tebako project.
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
+ # Tebako - an executable packager
29
+ module Tebako
30
+ module Packager
31
+ # Ruby patching literals (main.c)
32
+ module PatchMain
33
+ MAIN_C_SUBST_RB_MAIN = <<~SUBST
34
+ /* -- Start of tebako patch -- */
35
+ #include <tebako/tebako-main.h>
36
+ /* -- End of tebako patch -- */
37
+
38
+ static int
39
+ rb_main(int argc, char **argv)
40
+ SUBST
41
+
42
+ MAIN_C_SUBST_MAIN = <<~SUBST
43
+ /* -- Start of tebako patch -- */
44
+ #include <tebako/tebako-main.h>
45
+ /* -- End of tebako patch -- */
46
+
47
+ int
48
+ main(int argc, char **argv)
49
+ SUBST
50
+
51
+ MAIN_C_SUBST_RB_MAIN_INNER = <<~SUBST
52
+ ruby_init();
53
+ /* -- Start of tebako patch -- */
54
+ if (!tebako_is_running_miniruby())
55
+ {
56
+ VALUE cwd = rb_str_new_cstr(tebako_original_pwd());
57
+ rb_gv_set("$tebako_original_pwd", cwd);
58
+ }
59
+ /* -- End of tebako patch -- */
60
+ SUBST
61
+
62
+ MAIN_C_SUBST_MAIN_INNER = <<~SUBST
63
+ ruby_sysinit(&argc, &argv);
64
+ /* -- Start of tebako patch -- */
65
+ if (tebako_main(&argc, &argv) != 0) {
66
+ printf("Tebako intialization failed.");
67
+ return -1;
68
+ }
69
+ /* -- End of tebako patch -- */
70
+ SUBST
71
+
72
+ class << self
73
+ def get_main_c_patch(ruby_ver)
74
+ {
75
+ get_main_c_main_pattern(ruby_ver) => get_main_c_main_subst(ruby_ver),
76
+ "ruby_init();" => MAIN_C_SUBST_RB_MAIN_INNER,
77
+ " ruby_sysinit(&argc, &argv);" => MAIN_C_SUBST_MAIN_INNER
78
+ }
79
+ end
80
+
81
+ private
82
+
83
+ def get_main_c_main_pattern(ruby_ver)
84
+ ruby_ver.ruby32? ? "static int\nrb_main(int argc, char **argv)" : "int\nmain(int argc, char **argv)"
85
+ end
86
+
87
+ def get_main_c_main_subst(ruby_ver)
88
+ ruby_ver.ruby32? ? MAIN_C_SUBST_RB_MAIN : MAIN_C_SUBST_MAIN
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024-2025 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of the Tebako project.
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_relative "patch"
29
+ # Tebako - an executable packager
30
+ module Tebako
31
+ module Packager
32
+ # Shared accross Pass1Patch and RybugemsUpdatePatch
33
+ class RubygemsPatch < Patch
34
+ RUBYGEMS_OPENSSL_RB_SUBST = <<~SUBST
35
+ # Start of tebako patch
36
+ require "openssl"
37
+ # End of tebako patch
38
+ autoload :OpenSSL, "openssl"
39
+ SUBST
40
+
41
+ RUBYGEMS_OPENSSL_RB_PATCH = {
42
+ 'autoload :OpenSSL, "openssl"' => RUBYGEMS_OPENSSL_RB_SUBST
43
+ }.freeze
44
+
45
+ def initialize(mount_point)
46
+ super()
47
+ @mount_point = mount_point
48
+ end
49
+
50
+ protected
51
+
52
+ def rubygems_path_support_patch(mount_point)
53
+ patch = <<~SUBST
54
+ # -- Start of tebako patch --
55
+ @home = Gem.default_dir unless @home.index("#{mount_point}") == 0 unless env["TEBAKO_PASS_THROUGH"]
56
+ # -- End of tebako patch --
57
+ @path = split_gem_path env["GEM_PATH"], @home
58
+ # -- Start of tebako patch --
59
+ @path.keep_if do |xpath|
60
+ xpath.index("#{mount_point}") == 0
61
+ end unless env["TEBAKO_PASS_THROUGH"]
62
+ # -- End of tebako patch --
63
+ SUBST
64
+
65
+ {
66
+ ' @path = split_gem_path env["GEM_PATH"], @home' => patch
67
+ }
68
+ end
69
+ end
70
+
71
+ # Rubygems patch after update
72
+ class RubygemsUpdatePatch < RubygemsPatch
73
+ def patch_map
74
+ pm = {
75
+ "rubygems/openssl.rb" => RUBYGEMS_OPENSSL_RB_PATCH,
76
+ "rubygems/path_support.rb" => rubygems_path_support_patch(@mount_point)
77
+ }
78
+ pm.merge!(super)
79
+ pm.freeze
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2021-2025 [Ribose Inc](https://www.ribose.com).
4
+ # All rights reserved.
5
+ # This file is a part of the Tebako project.
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 "fileutils"
29
+ require "find"
30
+ require "pathname"
31
+
32
+ require_relative "error"
33
+ require_relative "deploy_helper"
34
+ require_relative "ruby_builder"
35
+ require_relative "stripper"
36
+ require_relative "packager/pass1_patch"
37
+ require_relative "packager/pass1a_patch"
38
+ require_relative "packager/pass2_patch_crt"
39
+ require_relative "packager/patch_helpers"
40
+
41
+ # Tebako - an executable packager
42
+ module Tebako
43
+ # Tebako packaging support (internal)
44
+ module Packager
45
+ FILES_TO_RESTORE = %w[
46
+ common.mk
47
+ configure
48
+ config.status
49
+ dir.c
50
+ dln.c
51
+ file.c
52
+ gem_prelude.rb
53
+ io.c
54
+ main.c
55
+ Makefile
56
+ ruby.c
57
+ thread_pthread.c
58
+ util.c
59
+ ext/bigdecimal/bigdecimal.h
60
+ ext/Setup
61
+ cygwin/GNUmakefile.in
62
+ include/ruby/onigmo.h
63
+ lib/rubygems/openssl.rb
64
+ lib/rubygems/path_support.rb
65
+ template/Makefile.in
66
+ tool/mkconfig.rb
67
+ win32/winmain.c
68
+ win32/file.c
69
+ ].freeze
70
+
71
+ class << self
72
+ # Create implib
73
+ def create_implib(src_dir, package_src_dir, app_name, ruby_ver)
74
+ a_name = File.basename(app_name, ".*")
75
+ create_def(src_dir, a_name)
76
+ puts " ... creating Windows import library"
77
+ params = ["dlltool", "-d", def_fname(src_dir, a_name), "-D", out_fname(a_name), "--output-lib",
78
+ lib_fname(package_src_dir, ruby_ver)]
79
+ BuildHelpers.run_with_capture(params)
80
+ end
81
+
82
+ # Deploy
83
+ def deploy(target_dir, pre_dir, ruby_ver, fs_root, fs_entrance, cwd) # rubocop:disable Metrics/ParameterLists
84
+ puts "-- Running deploy script"
85
+
86
+ deploy_helper = Tebako::DeployHelper.new(fs_root, fs_entrance, target_dir, pre_dir)
87
+ deploy_helper.configure(ruby_ver, cwd)
88
+ deploy_helper.deploy
89
+ Tebako::Stripper.strip(deploy_helper, target_dir)
90
+ end
91
+
92
+ def do_patch(patch_map, root)
93
+ patch_map.each { |fname, mapping| PatchHelpers.patch_file("#{root}/#{fname}", mapping) }
94
+ end
95
+
96
+ def finalize(src_dir, app_name, ruby_ver, patchelf, output_type)
97
+ puts "-- Running finalize script"
98
+
99
+ RubyBuilder.new(ruby_ver, src_dir).target_build(output_type)
100
+ exe_suffix = ScenarioManagerBase.new.exe_suffix
101
+ src_name = File.join(src_dir, "ruby#{exe_suffix}")
102
+ patchelf(src_name, patchelf)
103
+ package_name = "#{app_name}#{exe_suffix}"
104
+ # strip_or_copy(os_type, src_name, package_name)
105
+ Tebako::Stripper.strip_file(src_name, package_name)
106
+ puts "Created tebako #{output_type} at \"#{package_name}\""
107
+ end
108
+
109
+ # Init
110
+ def init(stash_dir, src_dir, pre_dir, bin_dir)
111
+ puts "-- Running init script"
112
+
113
+ puts " ... creating packaging environment at #{src_dir}"
114
+ PatchHelpers.recreate([src_dir, pre_dir, bin_dir])
115
+ FileUtils.cp_r "#{stash_dir}/.", src_dir
116
+ end
117
+
118
+ def mkdwarfs(deps_bin_dir, data_bin_file, data_src_dir, descriptor = nil)
119
+ puts "-- Running mkdwarfs script"
120
+ FileUtils.chmod("a+x", Dir.glob(File.join(deps_bin_dir, "mkdwarfs*")))
121
+ params = [File.join(deps_bin_dir, "mkdwarfs"), "-o", data_bin_file, "-i", data_src_dir, "--no-progress"]
122
+ params << "--header" << descriptor if descriptor
123
+ BuildHelpers.run_with_capture_v(params)
124
+ end
125
+
126
+ # Pass1
127
+ # Executed before Ruby build, patching ensures that Ruby itself is linked statically
128
+ def pass1(ostype, ruby_source_dir, mount_point, src_dir, ruby_ver)
129
+ puts "-- Running pass1 script"
130
+ PatchHelpers.recreate(src_dir)
131
+
132
+ # Roll all known patches
133
+ # Just in case we are recovering after some error
134
+ PatchHelpers.restore_and_save_files(FILES_TO_RESTORE, ruby_source_dir, strict: false)
135
+
136
+ patch = crt_pass1_patch(ostype, mount_point, ruby_ver)
137
+ do_patch(patch.patch_map, ruby_source_dir)
138
+ end
139
+
140
+ # Pass1A
141
+ # Patch gem_prelude.rb
142
+ def pass1a(ruby_source_dir)
143
+ puts "-- Running pass1a script"
144
+ patch = Pass1APatch.new
145
+ do_patch(patch.patch_map, ruby_source_dir)
146
+ end
147
+
148
+ # Pass2
149
+ # Creates packaging environment, patching ensures that tebako package is linked statically
150
+ def pass2(ostype, ruby_source_dir, deps_lib_dir, ruby_ver)
151
+ puts "-- Running pass2 script"
152
+
153
+ patch = crt_pass2_patch(ostype, deps_lib_dir, ruby_ver)
154
+ do_patch(patch.patch_map, ruby_source_dir)
155
+ end
156
+
157
+ # Stash
158
+ # Created and saves pristine Ruby environment that is used to deploy applications for packaging
159
+ def stash(src_dir, stash_dir, ruby_source_dir, ruby_ver)
160
+ puts "-- Running stash script"
161
+ RubyBuilder.new(ruby_ver, ruby_source_dir).toolchain_build
162
+
163
+ puts " ... saving pristine Ruby environment to #{stash_dir}"
164
+ PatchHelpers.recreate(stash_dir)
165
+ FileUtils.cp_r "#{src_dir}/.", stash_dir
166
+ end
167
+
168
+ private
169
+
170
+ def create_def(src_dir, app_name)
171
+ puts " ... creating Windows def file"
172
+ File.open(def_fname(src_dir, app_name), "w") do |file|
173
+ file.puts "LIBRARY #{out_fname(app_name)}"
174
+ File.readlines(File.join(src_dir, "tebako.def")).each do |line|
175
+ file.puts line unless line.include?("DllMain")
176
+ end
177
+ end
178
+ end
179
+
180
+ def def_fname(src_dir, app_name)
181
+ File.join(src_dir, "#{app_name}.def")
182
+ end
183
+
184
+ def out_fname(app_name)
185
+ File.join("#{app_name}.exe")
186
+ end
187
+
188
+ def lib_fname(src_dir, ruby_ver)
189
+ File.join(src_dir, "lib", "libx64-ucrt-ruby#{ruby_ver.lib_version}.a")
190
+ end
191
+
192
+ def patchelf(src_name, patchelf)
193
+ return if patchelf.nil?
194
+
195
+ params = [patchelf, "--remove-needed-version", "libpthread.so.0", "GLIBC_PRIVATE", src_name]
196
+ BuildHelpers.run_with_capture(params)
197
+ end
198
+
199
+ # def strip_or_copy(_os_type, src_name, package_name)
200
+ # [TODO] On MSys strip sometimes creates a broken executable
201
+ # https://github.com/tamatebako/tebako/issues/172
202
+ # if Packager::PatchHelpers.msys?(os_type)
203
+ # FileUtils.cp(src_name, package_name)
204
+ # else
205
+ # Tebako::Stripper.strip_file(src_name, package_name)
206
+ # end
207
+ # end
208
+ end
209
+ end
210
+ end