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,78 @@
|
|
|
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
|
+
require "pathname"
|
|
29
|
+
require "fileutils"
|
|
30
|
+
|
|
31
|
+
require_relative "options_manager"
|
|
32
|
+
require_relative "scenario_manager"
|
|
33
|
+
require_relative "package_descriptor"
|
|
34
|
+
require_relative "packager"
|
|
35
|
+
|
|
36
|
+
module Tebako
|
|
37
|
+
# Tebako application package descriptor
|
|
38
|
+
class PackagerLite
|
|
39
|
+
def initialize(options_manager, scenario_manager)
|
|
40
|
+
@opts = options_manager
|
|
41
|
+
@scm = scenario_manager
|
|
42
|
+
@scm.configure_scenario
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def codegen
|
|
46
|
+
puts "-- Generating files"
|
|
47
|
+
Tebako::Codegen.generate_package_descriptor(@opts, @scm)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def create_implib
|
|
51
|
+
rv = Tebako::RubyVersion.new(@opts.ruby_ver)
|
|
52
|
+
bname = if @opts.mode == "application"
|
|
53
|
+
@opts.ref
|
|
54
|
+
else # @opts.mode == "both"
|
|
55
|
+
@opts.package
|
|
56
|
+
end
|
|
57
|
+
Tebako::Packager.create_implib(@opts.ruby_src_dir, @opts.data_src_dir, bname, rv)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_package
|
|
61
|
+
deploy
|
|
62
|
+
FileUtils.rm_f(name)
|
|
63
|
+
Tebako::Packager.mkdwarfs(@opts.deps_bin_dir, name, @opts.data_src_dir, codegen)
|
|
64
|
+
puts "Created tebako #{@opts.output_type_second} at \"#{name}\""
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def deploy
|
|
68
|
+
Tebako::Packager.init(@opts.stash_dir, @opts.data_src_dir, @opts.data_pre_dir, @opts.data_bin_dir)
|
|
69
|
+
create_implib if @scm.msys?
|
|
70
|
+
Tebako::Packager.deploy(@opts.data_src_dir, @opts.data_pre_dir, @opts.rv, @opts.root, @scm.fs_entrance, @opts.cwd)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def name
|
|
74
|
+
bname = Pathname.new(@opts.package).cleanpath.to_s
|
|
75
|
+
@name ||= "#{bname}.tebako"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
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 "fileutils"
|
|
29
|
+
require "find"
|
|
30
|
+
|
|
31
|
+
require_relative "build_helpers"
|
|
32
|
+
|
|
33
|
+
# Tebako - an executable packager
|
|
34
|
+
module Tebako
|
|
35
|
+
# Tebako packaging support (ruby builder)
|
|
36
|
+
class RubyBuilder
|
|
37
|
+
def initialize(ruby_ver, src_dir)
|
|
38
|
+
@ruby_ver = ruby_ver
|
|
39
|
+
@src_dir = src_dir
|
|
40
|
+
@ncores = ScenarioManagerBase.new.ncores
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Ruby's parallel build can race on ext/extinit.o: the `ruby` link step can start before
|
|
44
|
+
# extinit.o is (re)built after configure-ext.mk is regenerated, giving
|
|
45
|
+
# "clang: error: no such file or directory: 'ext/extinit.o'". A second, serial pass is
|
|
46
|
+
# mostly cached and builds the raced target deterministically, so retry once serially.
|
|
47
|
+
def make_target(*args)
|
|
48
|
+
BuildHelpers.run_with_capture(["make", *args, "-j#{@ncores}"])
|
|
49
|
+
rescue Tebako::Error
|
|
50
|
+
BuildHelpers.run_with_capture(["make", *args])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Final build of tebako package
|
|
54
|
+
def toolchain_build
|
|
55
|
+
puts " ... building toolchain Ruby"
|
|
56
|
+
Dir.chdir(@src_dir) do
|
|
57
|
+
make_target
|
|
58
|
+
make_target("install")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Final build of tebako package
|
|
63
|
+
def target_build(output_type)
|
|
64
|
+
puts " ... building tebako #{output_type}"
|
|
65
|
+
Dir.chdir(@src_dir) do
|
|
66
|
+
make_target("ruby") if @ruby_ver.ruby3x?
|
|
67
|
+
make_target
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
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
|
+
require "bundler"
|
|
29
|
+
require_relative "error"
|
|
30
|
+
|
|
31
|
+
# Tebako - an executable packager
|
|
32
|
+
module Tebako
|
|
33
|
+
# Ruby version
|
|
34
|
+
class RubyVersion
|
|
35
|
+
# Supported Ruby versions: latest patch release of each maintained line (3.2+ through 4.0).
|
|
36
|
+
# Support for 2.7.x, 3.0.x and 3.1.x was dropped.
|
|
37
|
+
RUBY_VERSIONS = {
|
|
38
|
+
"3.2.11" => "b3eeabd6636f334531db3ffdc3229eb05e524740e6c84fdc043720573cf2f8b2",
|
|
39
|
+
"3.3.11" => "59f0fafb1a59a05dc3765117af3fa68e153eb48254708549f321c1e9e078d7a0",
|
|
40
|
+
"3.4.10" => "ecee2d072a14f2d14347dd56dfd8fe5c3130abf5117bfaacbda0f4ef9cc429ec",
|
|
41
|
+
"4.0.6" => "837d299e8f7ddf2be31a229a7a7e019d354979825117989acb3b32b1a9be262a"
|
|
42
|
+
}.freeze
|
|
43
|
+
|
|
44
|
+
MIN_RUBY_VERSION_WINDOWS = "3.2.11"
|
|
45
|
+
DEFAULT_RUBY_VERSION = "4.0.6"
|
|
46
|
+
|
|
47
|
+
def initialize(ruby_version)
|
|
48
|
+
@ruby_version = ruby_version.nil? ? DEFAULT_RUBY_VERSION : ruby_version
|
|
49
|
+
|
|
50
|
+
run_checks
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
attr_reader :ruby_version
|
|
54
|
+
|
|
55
|
+
def api_version
|
|
56
|
+
@api_version ||= "#{@ruby_version.split(".")[0..1].join(".")}.0"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def extend_ruby_version
|
|
60
|
+
@extend_ruby_version ||= [@ruby_version, RUBY_VERSIONS[@ruby_version]]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def lib_version
|
|
64
|
+
@lib_version ||= "#{@ruby_version.split(".")[0..1].join}0"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Version predicates are "this behavior applies to this version and newer", compared on
|
|
68
|
+
# Gem::Version so they are correct for Ruby 4.x (major != 3) and for two-digit patch levels
|
|
69
|
+
# (e.g. 3.3.11, 3.4.10). Ruby 4.0 satisfies the >= 3.x gates by design - it inherits the
|
|
70
|
+
# latest (3.4+) build behavior.
|
|
71
|
+
def ruby3x?
|
|
72
|
+
@ruby3x ||= at_least?("3.0.0")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def ruby31?
|
|
76
|
+
@ruby31 ||= at_least?("3.1.0")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def ruby32?
|
|
80
|
+
@ruby32 ||= at_least?("3.2.0")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def ruby32only?
|
|
84
|
+
@ruby32only ||= minor_line?(3, 2)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def ruby33?
|
|
88
|
+
@ruby33 ||= at_least?("3.3.0")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def ruby33only?
|
|
92
|
+
@ruby33only ||= minor_line?(3, 3)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def ruby3x7?
|
|
96
|
+
@ruby3x7 ||= ruby34? ||
|
|
97
|
+
(ruby32only? && teeny >= 7) ||
|
|
98
|
+
(ruby33only? && teeny >= 7)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def ruby34?
|
|
102
|
+
@ruby34 ||= at_least?("3.4.0")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def run_checks
|
|
106
|
+
version_check_format
|
|
107
|
+
version_check
|
|
108
|
+
version_check_msys
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def version_check
|
|
112
|
+
return if RUBY_VERSIONS.key?(@ruby_version)
|
|
113
|
+
|
|
114
|
+
raise Tebako::Error.new(
|
|
115
|
+
"Ruby version #{@ruby_version} is not supported",
|
|
116
|
+
110
|
|
117
|
+
)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def version_check_format
|
|
121
|
+
return if @ruby_version =~ /^\d+\.\d+\.\d+$/
|
|
122
|
+
|
|
123
|
+
raise Tebako::Error.new("Invalid Ruby version format '#{@ruby_version}'. Expected format: x.y.z", 109)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def version_check_msys
|
|
127
|
+
if Gem::Version.new(@ruby_version) < Gem::Version.new(MIN_RUBY_VERSION_WINDOWS) && ScenarioManagerBase.new.msys?
|
|
128
|
+
raise Tebako::Error.new("Ruby version #{@ruby_version} is not supported on Windows", 111)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def gem_version
|
|
135
|
+
@gem_version ||= Gem::Version.new(@ruby_version)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def segments
|
|
139
|
+
@segments ||= gem_version.segments
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def at_least?(version)
|
|
143
|
+
gem_version >= Gem::Version.new(version)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def teeny
|
|
147
|
+
segments[2].to_i
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def minor_line?(major, minor)
|
|
151
|
+
segments[0] == major && segments[1] == minor
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Ruby version with Gemfile definition
|
|
156
|
+
class RubyVersionWithGemfile < RubyVersion
|
|
157
|
+
def initialize(ruby_version, gemfile_path)
|
|
158
|
+
# Assuming that it does not attempt to load any gems or resolve dependencies
|
|
159
|
+
# this can be done with any bundler version
|
|
160
|
+
ruby_v = Bundler::Definition.build(gemfile_path, nil, nil).ruby_version&.versions
|
|
161
|
+
if ruby_v.nil?
|
|
162
|
+
super(ruby_version)
|
|
163
|
+
else
|
|
164
|
+
process_gemfile_ruby_version(ruby_version, ruby_v)
|
|
165
|
+
end
|
|
166
|
+
rescue Tebako::Error
|
|
167
|
+
raise
|
|
168
|
+
rescue StandardError => e
|
|
169
|
+
Tebako.packaging_error(115, e.message)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def process_gemfile_ruby_version(ruby_version, ruby_v)
|
|
173
|
+
puts "-- Found Gemfile with Ruby requirements #{ruby_v}"
|
|
174
|
+
requirement = Gem::Requirement.new(ruby_v)
|
|
175
|
+
|
|
176
|
+
if ruby_version.nil?
|
|
177
|
+
process_gemfile_ruby_version_ud(requirement)
|
|
178
|
+
else
|
|
179
|
+
process_gemfile_ruby_version_d(ruby_version, requirement)
|
|
180
|
+
end
|
|
181
|
+
run_checks
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def process_gemfile_ruby_version_d(ruby_version, requirement)
|
|
185
|
+
current_version = Gem::Version.new(ruby_version)
|
|
186
|
+
unless requirement.satisfied_by?(current_version)
|
|
187
|
+
raise Tebako::Error.new("Ruby version #{ruby_version} does not satisfy requirement '#{requirement}'", 116)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
@ruby_version = ruby_version
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def process_gemfile_ruby_version_ud(requirement)
|
|
194
|
+
available_versions = RUBY_VERSIONS.keys.map { |v| Gem::Version.new(v) }
|
|
195
|
+
matching_version = available_versions.find { |v| requirement.satisfied_by?(v) }
|
|
196
|
+
puts "-- Found matching Ruby version #{matching_version}" if matching_version
|
|
197
|
+
|
|
198
|
+
unless matching_version
|
|
199
|
+
raise Tebako::Error.new("No available Ruby version satisfies requirement #{requirement}",
|
|
200
|
+
116)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
@ruby_version = matching_version.to_s
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,251 @@
|
|
|
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 "pathname"
|
|
29
|
+
require "bundler"
|
|
30
|
+
|
|
31
|
+
require_relative "error"
|
|
32
|
+
|
|
33
|
+
# Tebako - an executable packager
|
|
34
|
+
module Tebako
|
|
35
|
+
# Minimum bundler / rubygems versions tebako pins when it has to install or update them
|
|
36
|
+
# (e.g. Gemfile-driven bundler resolution). These provide correct linux-gnu / linux-musl
|
|
37
|
+
# differentiation by bundler; supported Ruby lines (3.2+) ship compatible rubygems by default.
|
|
38
|
+
BUNDLER_VERSION = "2.4.22"
|
|
39
|
+
RUBYGEMS_VERSION = "3.4.22"
|
|
40
|
+
|
|
41
|
+
# A couple of static Scenario definitions
|
|
42
|
+
class ScenarioManagerBase
|
|
43
|
+
def initialize(ostype = RUBY_PLATFORM)
|
|
44
|
+
@ostype = ostype
|
|
45
|
+
@linux = @ostype =~ /linux/ ? true : false
|
|
46
|
+
@musl = @ostype =~ /linux-musl/ ? true : false
|
|
47
|
+
@macos = @ostype =~ /darwin/ ? true : false
|
|
48
|
+
@msys = @ostype =~ /msys|mingw|cygwin/ ? true : false
|
|
49
|
+
|
|
50
|
+
@fs_mount_point = @msys ? "A:/__tebako_memfs__" : "/__tebako_memfs__"
|
|
51
|
+
@exe_suffix = @msys ? ".exe" : ""
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
attr_reader :fs_mount_point, :exe_suffix
|
|
55
|
+
|
|
56
|
+
def b_env
|
|
57
|
+
u_flags = if @macos
|
|
58
|
+
"-DTARGET_OS_SIMULATOR=0 -DTARGET_OS_IPHONE=0 #{ENV.fetch("CXXFLAGS", nil)}"
|
|
59
|
+
elsif @msys
|
|
60
|
+
"-DGFLAGS_IS_A_DLL=0 #{ENV.fetch("CXXFLAGS", nil)}"
|
|
61
|
+
else
|
|
62
|
+
ENV.fetch("CXXFLAGS", nil)
|
|
63
|
+
end
|
|
64
|
+
@b_env ||= { "CXXFLAGS" => u_flags }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def linux?
|
|
68
|
+
@linux
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def linux_gnu?
|
|
72
|
+
@linux && !@musl
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def linux_musl?
|
|
76
|
+
@linux && @musl
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def m_files
|
|
80
|
+
# [TODO]
|
|
81
|
+
# Ninja generates incorrect script for tebako press target -- gets lost in a chain custom targets
|
|
82
|
+
# Using makefiles has negative performance impact so it needs to be fixed
|
|
83
|
+
|
|
84
|
+
@m_files ||= if @linux || @macos
|
|
85
|
+
"Unix Makefiles"
|
|
86
|
+
elsif @msys
|
|
87
|
+
"MinGW Makefiles"
|
|
88
|
+
else
|
|
89
|
+
raise Tebako::Error.new("#{RUBY_PLATFORM} is not supported.", 112)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def macos?
|
|
94
|
+
@macos
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def msys?
|
|
98
|
+
@msys
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def musl?
|
|
102
|
+
@musl
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def ncores
|
|
106
|
+
if @ncores.nil?
|
|
107
|
+
if @macos
|
|
108
|
+
out, st = Open3.capture2e("sysctl", "-n", "hw.ncpu")
|
|
109
|
+
else
|
|
110
|
+
out, st = Open3.capture2e("nproc", "--all")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
@ncores = !st.signaled? && st.exitstatus.zero? ? out.strip.to_i : 4
|
|
114
|
+
end
|
|
115
|
+
@ncores
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Manages packaging scenario based on input files (gemfile, gemspec, etc)
|
|
120
|
+
class ScenarioManager < ScenarioManagerBase
|
|
121
|
+
def initialize(fs_root, fs_entrance)
|
|
122
|
+
super()
|
|
123
|
+
@with_gemfile = @with_lockfile = @needs_bundler = false
|
|
124
|
+
@bundler_version = BUNDLER_VERSION
|
|
125
|
+
initialize_root(fs_root)
|
|
126
|
+
initialize_entry_point(fs_entrance || "stub.rb")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
attr_reader :fs_entry_point, :fs_entrance, :gemfile_path, :needs_bundler, :with_gemfile
|
|
130
|
+
|
|
131
|
+
def bundler_reference
|
|
132
|
+
@needs_bundler ? "_#{@bundler_version}_" : nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def configure_scenario
|
|
136
|
+
lookup_files
|
|
137
|
+
|
|
138
|
+
case @gs_length
|
|
139
|
+
when 0
|
|
140
|
+
configure_scenario_no_gemspec
|
|
141
|
+
when 1
|
|
142
|
+
@scenario = @with_gemfile ? :gemspec_and_gemfile : :gemspec
|
|
143
|
+
else
|
|
144
|
+
raise Tebako::Error, "Multiple Ruby gemspecs found in #{@fs_root}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def configure_scenario_no_gemspec
|
|
151
|
+
@fs_entry_point = "/local/#{@fs_entrance}" if @with_gemfile || @g_length.zero?
|
|
152
|
+
|
|
153
|
+
@scenario = if @with_gemfile
|
|
154
|
+
:gemfile
|
|
155
|
+
elsif @g_length.positive?
|
|
156
|
+
:gem
|
|
157
|
+
else
|
|
158
|
+
:simple_script
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def initialize_entry_point(fs_entrance)
|
|
163
|
+
@fs_entrance = Pathname.new(fs_entrance).cleanpath.to_s
|
|
164
|
+
|
|
165
|
+
if Pathname.new(@fs_entrance).absolute?
|
|
166
|
+
Tebako.packaging_error 114 unless @fs_entrance.start_with?(@fs_root)
|
|
167
|
+
|
|
168
|
+
fetmp = @fs_entrance
|
|
169
|
+
@fs_entrance = Pathname.new(@fs_entrance).relative_path_from(Pathname.new(@fs_root)).to_s
|
|
170
|
+
puts "-- Absolute path to entry point '#{fetmp}' will be reduced to '#{@fs_entrance}' relative to '#{@fs_root}'"
|
|
171
|
+
end
|
|
172
|
+
# Can check after deploy, because entry point can be generated during bundle install or gem install
|
|
173
|
+
# Tebako.packaging_error 106 unless File.file?(File.join(@fs_root, @fs_entrance))
|
|
174
|
+
@fs_entry_point = "/bin/#{@fs_entrance}"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def initialize_root(fs_root)
|
|
178
|
+
Tebako.packaging_error 107 unless Dir.exist?(fs_root)
|
|
179
|
+
p_root = Pathname.new(fs_root).cleanpath
|
|
180
|
+
Tebako.packaging_error 113 unless p_root.absolute?
|
|
181
|
+
@fs_root = p_root.realpath.to_s
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def lookup_files
|
|
185
|
+
@gs_length = Dir.glob(File.join(@fs_root, "*.gemspec")).length
|
|
186
|
+
@g_length = Dir.glob(File.join(@fs_root, "*.gem")).length
|
|
187
|
+
@with_gemfile = File.exist?(@gemfile_path = File.join(@fs_root, "Gemfile"))
|
|
188
|
+
@with_lockfile = File.exist?(@lockfile_path = File.join(@fs_root, "Gemfile.lock"))
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Configure scenraio and do bundler resolution
|
|
193
|
+
class ScenarioManagerWithBundler < ScenarioManager
|
|
194
|
+
protected
|
|
195
|
+
|
|
196
|
+
def lookup_files
|
|
197
|
+
super
|
|
198
|
+
if @with_lockfile
|
|
199
|
+
update_bundler_version_from_lockfile(@lockfile_path)
|
|
200
|
+
elsif @with_gemfile
|
|
201
|
+
update_bundler_version_from_gemfile(@gemfile_path)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
private
|
|
206
|
+
|
|
207
|
+
def store_compatible_bundler_version(requirement)
|
|
208
|
+
fetcher = Gem::SpecFetcher.fetcher
|
|
209
|
+
tuples = fetcher.detect(:released) do |name_tuple|
|
|
210
|
+
name_tuple.name == "bundler" && requirement.satisfied_by?(name_tuple.version)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
Tebako.packaging_error 119 if tuples.empty?
|
|
214
|
+
|
|
215
|
+
# Get latest compatible version
|
|
216
|
+
@bundler_version = tuples.map { |tuple, _| tuple.version }.max.to_s
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def update_bundler_version_from_gemfile(gemfile_path)
|
|
220
|
+
# Build definition without lockfile
|
|
221
|
+
definition = Bundler::Definition.build(gemfile_path, nil, nil)
|
|
222
|
+
|
|
223
|
+
# Get bundler dependency from Gemfile
|
|
224
|
+
bundler_dep = definition.dependencies.find { |d| d.name == "bundler" }
|
|
225
|
+
|
|
226
|
+
return unless bundler_dep
|
|
227
|
+
|
|
228
|
+
@needs_bundler = true
|
|
229
|
+
min_requirement = Gem::Requirement.create(">= #{Tebako::BUNDLER_VERSION}")
|
|
230
|
+
requirement = Gem::Requirement.create(bundler_dep.requirement, min_requirement)
|
|
231
|
+
|
|
232
|
+
store_compatible_bundler_version(requirement)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def update_bundler_version_from_lockfile(lockfile_path)
|
|
236
|
+
puts " ... using lockfile at #{@lockfile_path}"
|
|
237
|
+
Tebako.packaging_error 117 unless File.exist?(lockfile_path)
|
|
238
|
+
|
|
239
|
+
lockfile_content = File.read(lockfile_path)
|
|
240
|
+
Tebako.packaging_error 117 unless lockfile_content =~ /BUNDLED WITH\n\s+(#{Gem::Version::VERSION_PATTERN})\n/
|
|
241
|
+
|
|
242
|
+
@bundler_version = ::Regexp.last_match(1)
|
|
243
|
+
@needs_bundler = true
|
|
244
|
+
|
|
245
|
+
bundler_requirement = Gem::Requirement.new(">= #{BUNDLER_VERSION}")
|
|
246
|
+
return if bundler_requirement.satisfied_by?(Gem::Version.new(@bundler_version))
|
|
247
|
+
|
|
248
|
+
Tebako.packaging_error 118, " : #{@bundler_version} requested, #{BUNDLER_VERSION} minimum required"
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|