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.
- checksums.yaml +7 -0
- data/.clang-format +4 -0
- data/Brewfile +23 -0
- data/CMakeLists.txt +464 -0
- data/CODE_OF_CONDUCT.adoc +128 -0
- data/CONTRIBUTING.adoc +294 -0
- data/Gemfile +31 -0
- data/INSTALLATION.adoc +233 -0
- data/LICENSE.md +33 -0
- data/README.adoc +1363 -0
- data/Rakefile +35 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/cmake/copy_dir.cmake +29 -0
- data/common.env +5 -0
- data/exe/rbe-tebako +32 -0
- data/exe/rbe-tebako-packager +77 -0
- data/include/tebako/tebako-fs.h +43 -0
- data/include/tebako/tebako-main.h +42 -0
- data/include/tebako/tebako-prism.h +51 -0
- data/lib/rbe-tebako.rb +6 -0
- data/lib/tebako/build_helpers.rb +77 -0
- data/lib/tebako/cache_manager.rb +112 -0
- data/lib/tebako/cli.rb +220 -0
- data/lib/tebako/cli_helpers.rb +165 -0
- data/lib/tebako/codegen.rb +252 -0
- data/lib/tebako/deploy_helper.rb +258 -0
- data/lib/tebako/error.rb +70 -0
- data/lib/tebako/options_manager.rb +338 -0
- data/lib/tebako/package_descriptor.rb +143 -0
- data/lib/tebako/packager/pass1_patch.rb +266 -0
- data/lib/tebako/packager/pass1a_patch.rb +55 -0
- data/lib/tebako/packager/pass2_patch.rb +140 -0
- data/lib/tebako/packager/pass2_patch_crt.rb +46 -0
- data/lib/tebako/packager/pass2msys_patch.rb +190 -0
- data/lib/tebako/packager/patch.rb +54 -0
- data/lib/tebako/packager/patch_buildsystem.rb +124 -0
- data/lib/tebako/packager/patch_helpers.rb +109 -0
- data/lib/tebako/packager/patch_libraries.rb +188 -0
- data/lib/tebako/packager/patch_literals.rb +275 -0
- data/lib/tebako/packager/patch_main.rb +93 -0
- data/lib/tebako/packager/rubygems_patch.rb +83 -0
- data/lib/tebako/packager.rb +210 -0
- data/lib/tebako/packager_lite.rb +78 -0
- data/lib/tebako/ruby_builder.rb +71 -0
- data/lib/tebako/ruby_version.rb +206 -0
- data/lib/tebako/scenario_manager.rb +251 -0
- data/lib/tebako/stripper.rb +135 -0
- data/lib/tebako/version.rb +30 -0
- data/lib/tebako.rb +34 -0
- data/src/tebako-main.cpp +168 -0
- data/tools/.gitattributes +4 -0
- data/tools/.github/workflows/build-containers.yml +190 -0
- data/tools/.github/workflows/lint.yml +41 -0
- data/tools/.github/workflows/test.yml +331 -0
- data/tools/.gitignore +1 -0
- data/tools/README.md +49 -0
- data/tools/ci-scripts/arm-brew-install.sh +43 -0
- data/tools/ci-scripts/arm-brew-setup.sh +33 -0
- data/tools/ci-scripts/level-up.sh +35 -0
- data/tools/ci-scripts/patch-fbthrift.sh +94 -0
- data/tools/ci-scripts/patch-folly.sh +551 -0
- data/tools/ci-scripts/patch-glog.sh +57 -0
- data/tools/ci-scripts/patch-zstd.sh +57 -0
- data/tools/ci-scripts/tools.sh +63 -0
- data/tools/ci-scripts/x86-brew-install.sh +43 -0
- data/tools/ci-scripts/x86-brew-setup.sh +33 -0
- data/tools/cmake-scripts/def-external-project.cmake +96 -0
- data/tools/cmake-scripts/macos-environment.cmake +91 -0
- data/tools/cmake-scripts/msys-environment.cmake +78 -0
- data/tools/cmake-scripts/setup-libarchive.cmake +93 -0
- data/tools/cmake-scripts/setup-libfmt.cmake +61 -0
- data/tools/cmake-scripts/setup-libhowardhinnerdate.cmake +55 -0
- data/tools/cmake-scripts/setup-libutfcpp.cmake +56 -0
- data/tools/cmake-scripts/version.cmake +162 -0
- data/tools/docker/alpine-3.17-dev.Dockerfile +49 -0
- data/tools/docker/tools/tools.sh +66 -0
- data/tools/docker/ubuntu-20.04-dev.Dockerfile +51 -0
- data/tools/dwarfs-test-helper/CMakeLists.txt +34 -0
- data/tools/include/pro-statvfs.h +57 -0
- data/tools/tests/cmake/CMakeLists.txt +81 -0
- data/tools/tests/setup-libfmt/CMakeLists.txt +35 -0
- data/tools/tests/setup-libhowardhinnerdate/CMakeLists.txt +35 -0
- data/tools/tests/setup-librachive/CMakeLists.txt +35 -0
- data/tools/tests/setup-libutfcpp/CMakeLists.txt +36 -0
- data/tools/tests/setup-openssl/CMakeLists.txt +36 -0
- 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
|