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,258 @@
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 "bundler"
29
+ require "fileutils"
30
+ require "find"
31
+
32
+ require_relative "error"
33
+ require_relative "build_helpers"
34
+ require_relative "packager/patch_helpers"
35
+ require_relative "scenario_manager"
36
+
37
+ require_relative "packager/patch"
38
+ require_relative "packager/rubygems_patch"
39
+
40
+ # Tebako - an executable packager
41
+ module Tebako
42
+ # Tebako packaging support (deployer)
43
+ class DeployHelper < ScenarioManagerWithBundler # rubocop:disable Metrics/ClassLength
44
+ def initialize(fs_root, fs_entrance, target_dir, pre_dir)
45
+ super(fs_root, fs_entrance)
46
+ @fs_root = fs_root
47
+ @fs_entrance = fs_entrance
48
+ @target_dir = target_dir
49
+ @pre_dir = pre_dir
50
+ @verbose = %w[yes true].include?(ENV.fetch("VERBOSE", nil))
51
+ end
52
+
53
+ attr_reader :gem_home
54
+
55
+ def configure(ruby_ver, cwd)
56
+ @ruby_ver = ruby_ver
57
+ @needs_bundler = true unless @ruby_ver.ruby31?
58
+ @cwd = cwd
59
+
60
+ @tbd = File.join(@target_dir, "bin")
61
+ @tgd = @gem_home = File.join(@target_dir, "lib", "ruby", "gems", @ruby_ver.api_version)
62
+ @tld = File.join(@target_dir, "local")
63
+
64
+ configure_scenario
65
+ configure_commands
66
+ end
67
+
68
+ def deploy
69
+ BuildHelpers.with_env(deploy_env) do
70
+ update_rubygems
71
+ system("#{@gem_command} env") if @verbose
72
+ install_gem("tebako-runtime")
73
+ install_gem("bundler", @bundler_version) if @needs_bundler
74
+ deploy_solution
75
+ check_cwd
76
+ end
77
+ end
78
+
79
+ def deploy_env
80
+ {
81
+ "GEM_HOME" => gem_home,
82
+ "GEM_PATH" => gem_home,
83
+ "GEM_SPEC_CACHE" => File.join(@target_dir, "spec_cache"),
84
+ "TEBAKO_PASS_THROUGH" => "1"
85
+ }
86
+ end
87
+
88
+ def install_gem(name, ver = nil)
89
+ puts " ... installing #{name} gem#{" version #{ver}" if ver}"
90
+
91
+ params = [@gem_command, "install", name.to_s]
92
+ params += ["-v", ver.to_s] if ver
93
+ params += ["--no-document", "--install-dir", @tgd, "--bindir", @tbd]
94
+ params += ["--platform", "ruby"] if msys?
95
+ BuildHelpers.run_with_capture_v(params)
96
+ end
97
+
98
+ def update_rubygems
99
+ return if @ruby_ver.ruby31?
100
+
101
+ puts " ... updating rubygems to #{Tebako::RUBYGEMS_VERSION}"
102
+ BuildHelpers.run_with_capture_v([@gem_command, "update", "--no-doc", "--system",
103
+ Tebako::RUBYGEMS_VERSION])
104
+
105
+ patch = Packager::RubygemsUpdatePatch.new(@fs_mount_point).patch_map
106
+ Packager.do_patch(patch, "#{@target_dir}/lib/ruby/site_ruby/#{@ruby_ver.api_version}")
107
+ end
108
+
109
+ private
110
+
111
+ def bundle_config
112
+ bundle_config_option(["build.ffi", "--disable-system-libffi"])
113
+ bundle_config_option(["build.nokogiri", @nokogiri_option])
114
+ bundle_config_option(["force_ruby_platform", @force_ruby_platform])
115
+ end
116
+
117
+ def bundle_config_option(opt)
118
+ BuildHelpers.run_with_capture_v([@bundler_command, bundler_reference, "config", "set", "--local"] + opt)
119
+ end
120
+
121
+ def check_entry_point(entry_point_root)
122
+ fs_entry_point = File.join(entry_point_root, @fs_entrance)
123
+ puts " ... target entry point will be at #{File.join(@fs_mount_point, fs_entry_point)}"
124
+
125
+ return if File.exist?(File.join(@target_dir, fs_entry_point))
126
+
127
+ raise Tebako::Error.new("Entry point #{fs_entry_point} does not exist or is not accessible", 106)
128
+ end
129
+
130
+ def check_cwd
131
+ return if @cwd.nil?
132
+
133
+ cwd_full = File.join(@target_dir, @cwd)
134
+ return if File.directory?(cwd_full)
135
+
136
+ raise Tebako::Error.new("Package working directory #{@cwd} does not exist", 108)
137
+ end
138
+
139
+ def collect_and_deploy_gem(gemspec)
140
+ puts " ... collecting gem from gemspec #{gemspec}"
141
+
142
+ copy_files(@pre_dir)
143
+
144
+ Dir.chdir(@pre_dir) do
145
+ # spec = Bundler.load_gemspec(gemspec)
146
+ # puts spec.executables.first unless spec.executables.empty?
147
+ # puts spec.bindir
148
+
149
+ BuildHelpers.run_with_capture_v([@gem_command, "build", gemspec])
150
+ install_all_gems_or_fail
151
+ end
152
+
153
+ check_entry_point("bin")
154
+ end
155
+
156
+ def collect_and_deploy_gem_and_gemfile(gemspec)
157
+ puts " ... collecting gem from gemspec #{gemspec} and Gemfile"
158
+
159
+ copy_files(@pre_dir)
160
+
161
+ Dir.chdir(@pre_dir) do
162
+ bundle_config
163
+ puts " *** It may take a long time for a big project. It takes REALLY long time on Windows ***"
164
+ BuildHelpers.run_with_capture_v([@bundler_command, bundler_reference, "install", "--jobs=#{ncores}"])
165
+ BuildHelpers.run_with_capture_v([@bundler_command, bundler_reference, "exec", @gem_command, "build", gemspec])
166
+ install_all_gems_or_fail
167
+ end
168
+
169
+ check_entry_point("bin")
170
+ end
171
+
172
+ def configure_commands
173
+ if msys?
174
+ configure_commands_msys
175
+ else
176
+ configure_commands_not_msys
177
+ end
178
+
179
+ @gem_command = File.join(@tbd, "gem#{@cmd_suffix}")
180
+ @bundler_command = File.join(@tbd, "bundle#{@bat_suffix}")
181
+ end
182
+
183
+ def configure_commands_msys
184
+ @cmd_suffix = ".cmd"
185
+ @bat_suffix = ".bat"
186
+ @force_ruby_platform = "true"
187
+ @nokogiri_option = "--use-system-libraries"
188
+ end
189
+
190
+ def configure_commands_not_msys
191
+ @cmd_suffix = ""
192
+ @bat_suffix = ""
193
+ @force_ruby_platform = "false"
194
+ @nokogiri_option = "--no-use-system-libraries"
195
+ end
196
+
197
+ def copy_files(dest)
198
+ FileUtils.mkdir_p(dest)
199
+ if Dir.exist?(@fs_root) && File.readable?(@fs_root)
200
+ begin
201
+ FileUtils.cp_r(File.join(@fs_root, "."), dest)
202
+ rescue StandardError
203
+ raise Tebako::Error.new("#{@fs_root} does not exist or is not accessible.", 107)
204
+ end
205
+ return
206
+ end
207
+ raise Tebako::Error.new("#{@fs_root} is not accessible or is not a directory.", 107)
208
+ end
209
+
210
+ def deploy_gem(gem)
211
+ puts " ... installing Ruby gem from #{gem}"
212
+ copy_files(@pre_dir)
213
+ Dir.chdir(@pre_dir) { install_gem(gem) }
214
+ check_entry_point("bin")
215
+ end
216
+
217
+ def deploy_gemfile
218
+ puts " ... deploying Gemfile"
219
+ copy_files(@tld)
220
+
221
+ Dir.chdir(@tld) do
222
+ bundle_config
223
+ puts " *** It may take a long time for a big project. It takes REALLY long time on Windows ***"
224
+ BuildHelpers.run_with_capture_v([@bundler_command, bundler_reference, "install", "--jobs=#{ncores}"])
225
+ end
226
+
227
+ check_entry_point("local")
228
+ end
229
+
230
+ def deploy_simple_script
231
+ puts " ... collecting simple Ruby script from #{@fs_root}"
232
+ copy_files(@tld)
233
+ check_entry_point("local")
234
+ end
235
+
236
+ def deploy_solution # rubocop:disable Metrics/MethodLength
237
+ case @scenario
238
+ when :simple_script
239
+ deploy_simple_script
240
+ when :gem
241
+ deploy_gem(Dir.glob(File.join(@fs_root, "*.gem")).first)
242
+ when :gemfile
243
+ deploy_gemfile
244
+ when :gemspec
245
+ collect_and_deploy_gem(Dir.glob(File.join(@fs_root, "*.gemspec")).first)
246
+ when :gemspec_and_gemfile
247
+ collect_and_deploy_gem_and_gemfile(Dir.glob(File.join(@fs_root, "*.gemspec")).first)
248
+ end
249
+ end
250
+
251
+ def install_all_gems_or_fail
252
+ gem_files = Dir.glob("*.gem").map { |file| File.expand_path(file) }
253
+ raise Tebako::Error, "No gem files found after build" if gem_files.empty?
254
+
255
+ gem_files.each { |gem_file| install_gem(gem_file) }
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,70 @@
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
+ PACKAGING_ERRORS = {
31
+ 101 => "'tebako setup' configure step failed",
32
+ 102 => "'tebako setup' build step failed",
33
+ 103 => "'tebako press' configure step failed",
34
+ 104 => "'tebako press' build step failed",
35
+ 105 => "Failed to map MSys path to Windows",
36
+ 106 => "Entry point does not exist or is not accessible",
37
+ 107 => "Project root does not exist or is not accessible",
38
+ 108 => "Package working directory does not exist",
39
+ 109 => "Invalid Ruby version format",
40
+ 110 => "Ruby version is not supported",
41
+ 111 => "Ruby version is not supported on Windows",
42
+ 112 => "OS is not supported",
43
+ 113 => "Path to root shall be absolute. Relative path is not allowed",
44
+ 114 => "Entry point is not within the project root",
45
+ 115 => "Failed to load Gemfile",
46
+ 116 => "Ruby version does not satify Gemfile requirements",
47
+ 117 => "Failed to load Gemfile.lock",
48
+ 118 => "Bundler version in Gemfile.lock does satisfy minimal Tebako version requirememnts",
49
+ 119 => "Failed to find compatible bundler version",
50
+ 201 => "Warning. Could not create cache version file"
51
+ }.freeze
52
+
53
+ class << self
54
+ def packaging_error(code, extm = nil)
55
+ msg = PACKAGING_ERRORS[code]
56
+ msg += ": #{extm}" unless extm.nil?
57
+ msg = "Unknown packaging error" if msg.nil?
58
+ raise Tebako::Error.new msg, code
59
+ end
60
+ end
61
+
62
+ # Tebako error class
63
+ class Error < StandardError
64
+ def initialize(msg = "Unspecified error", code = 255)
65
+ @error_code = code
66
+ super(msg)
67
+ end
68
+ attr_accessor :error_code
69
+ end
70
+ end
@@ -0,0 +1,338 @@
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 "etc"
29
+ require "fileutils"
30
+ require "pathname"
31
+ require "rbconfig"
32
+
33
+ require_relative "codegen"
34
+ require_relative "error"
35
+ require_relative "ruby_version"
36
+ require_relative "version"
37
+
38
+ # Tebako - an executable packager
39
+ # Command-line interface methods
40
+ module Tebako
41
+ # Cli helpers
42
+ class OptionsManager # rubocop:disable Metrics/ClassLength
43
+ def initialize(options)
44
+ @options = options
45
+ @rv = Tebako::RubyVersion.new(@options["Ruby"])
46
+ @ruby_ver, @ruby_hash = @rv.extend_ruby_version
47
+ @scmb = ScenarioManagerBase.new
48
+ end
49
+
50
+ attr_reader :ruby_ver, :rv
51
+
52
+ def cfg_options
53
+ ## {v_parts[3]} may be something like rc1 that won't work with CMake
54
+ v_parts = Tebako::VERSION.split(".")
55
+ # Cannot use 'xxx' as parameters because it does not work in Windows shells
56
+ # So we have to use \"xxx\"
57
+ @cfg_options ||=
58
+ "-DCMAKE_BUILD_TYPE=Release -DRUBY_VER:STRING=\"#{@ruby_ver}\" -DRUBY_HASH:STRING=\"#{@ruby_hash}\" " \
59
+ "-DDEPS:STRING=\"#{deps}\" -G \"#{@scmb.m_files}\" -B \"#{output_folder}\" -S \"#{source}\" " \
60
+ "#{remove_glibc_private} -DTEBAKO_VERSION:STRING=\"#{v_parts[0]}.#{v_parts[1]}.#{v_parts[2]}\""
61
+ end
62
+
63
+ def cwd
64
+ f_cwd = @options["cwd"]&.gsub("\\", "/")
65
+ @cwd ||= f_cwd
66
+ end
67
+
68
+ def cwd_announce
69
+ @cwd_announce ||= cwd.nil? ? "<Host current directory>" : cwd
70
+ end
71
+
72
+ # DATA_BIN_DIR folder is used to create packaged filesystem
73
+ # set(DATA_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}/p)
74
+ def data_bin_dir
75
+ @data_bin_dir ||= File.join(output_folder, "p")
76
+ end
77
+
78
+ # Mode File(s) Content
79
+ # bundle fs.bin Application
80
+ # both fs.bin, fs2.bin Stub, application respectively
81
+ # runtime fs.bin Stub
82
+ # app fs2.bin Application
83
+
84
+ def data_bundle_file
85
+ @data_bundle_file ||= File.join(data_bin_dir, "fs.bin")
86
+ end
87
+
88
+ def data_stub_file
89
+ @data_stub_file ||= File.join(data_bin_dir, "fs.bin")
90
+ end
91
+
92
+ def data_app_file
93
+ @data_app_file ||= File.join(data_bin_dir, "fs2.bin")
94
+ end
95
+
96
+ # DATA_PRE_DIR folder is used to build gems that need to be packaged
97
+ # set(DATA_PRE_DIR ${CMAKE_CURRENT_BINARY_DIR}/r)
98
+ def data_pre_dir
99
+ @data_pre_dir ||= File.join(output_folder, "r")
100
+ end
101
+
102
+ # DATA_SRC_DIR folder is used to collect all files that need to be packaged
103
+ # set(DATA_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/s)
104
+ def data_src_dir
105
+ @data_src_dir ||= File.join(output_folder, "s")
106
+ end
107
+
108
+ def deps
109
+ @deps ||= File.join(prefix, "deps")
110
+ end
111
+
112
+ def deps_bin_dir
113
+ @deps_bin_dir ||= File.join(deps, "bin")
114
+ end
115
+
116
+ def deps_lib_dir
117
+ @deps_lib_dir ||= File.join(deps, "lib")
118
+ end
119
+
120
+ def folder_within_root?(folder)
121
+ folder_path = Pathname.new(folder.chomp("/"))
122
+ root_path = Pathname.new(root.chomp("/"))
123
+ folder_path.ascend do |path|
124
+ return true if path == root_path
125
+ end
126
+ false
127
+ end
128
+
129
+ def fs_current
130
+ fs_current = Dir.pwd
131
+ if @scmb.msys?
132
+ fs_current, cygpath_res = Open3.capture2e("cygpath", "-w", fs_current)
133
+ Tebako.packaging_error(101) unless cygpath_res.success?
134
+ fs_current.strip!
135
+ end
136
+ @fs_current ||= fs_current&.gsub("\\", "/")
137
+ end
138
+
139
+ def fs_entrance
140
+ @fs_entrance ||= @options["entry-point"]&.gsub("\\", "/")
141
+ end
142
+
143
+ def handle_nil_prefix
144
+ env_prefix = ENV.fetch("TEBAKO_PREFIX", nil)
145
+ if env_prefix.nil?
146
+ puts "No prefix specified, using ~/.tebako"
147
+ File.expand_path("~/.tebako")
148
+ else
149
+ puts "Using TEBAKO_PREFIX environment variable as prefix"
150
+ File.expand_path(env_prefix.gsub("\\", "/"))
151
+ end
152
+ end
153
+
154
+ def l_level
155
+ @l_level ||= @options["log-level"].nil? ? "error" : @options["log-level"]
156
+ end
157
+
158
+ def mode
159
+ @mode ||= @options["mode"].nil? ? "bundle" : @options["mode"]
160
+ end
161
+
162
+ def output_folder
163
+ @output_folder ||= File.join(prefix, "o")
164
+ end
165
+
166
+ def output_type_first
167
+ @output_type_first ||= %w[both runtime].include?(mode) ? "runtime package" : "package"
168
+ end
169
+
170
+ def output_type_second
171
+ "application package"
172
+ end
173
+
174
+ def package
175
+ package = if @options["output"].nil?
176
+ File.join(Dir.pwd, mode == "runtime" ? "tebako-runtime" : File.basename(fs_entrance, ".*"))
177
+ else
178
+ @options["output"]&.gsub("\\", "/")
179
+ end
180
+ @package ||= if relative?(package)
181
+ File.join(fs_current, package)
182
+ else
183
+ package
184
+ end
185
+ end
186
+
187
+ def package_within_root?
188
+ folder_within_root?(package)
189
+ end
190
+
191
+ def patchelf?
192
+ @options["patchelf"]
193
+ end
194
+
195
+ def prefix
196
+ @prefix ||= if @options["prefix"].nil?
197
+ handle_nil_prefix
198
+ elsif @options["prefix"] == "PWD"
199
+ Dir.pwd
200
+ else
201
+ File.expand_path(@options["prefix"]&.gsub("\\", "/"))
202
+ end
203
+ end
204
+
205
+ def prefix_within_root?
206
+ folder_within_root?(prefix)
207
+ end
208
+
209
+ def press_announce(is_msys)
210
+ case mode
211
+ when "application"
212
+ press_announce_application(is_msys)
213
+ when "both"
214
+ press_announce_both
215
+ when "bundle"
216
+ press_announce_bundle
217
+ when "runtime"
218
+ press_announce_runtime
219
+ end
220
+ end
221
+
222
+ def press_announce_ref(is_msys)
223
+ if is_msys
224
+ " referencing runtime at '#{ref}'"
225
+ else
226
+ ""
227
+ end
228
+ end
229
+
230
+ def press_announce_application(is_msys)
231
+ <<~ANN
232
+ Running tebako press at #{prefix}
233
+ Mode: 'application'
234
+ Ruby version: '#{@ruby_ver}'
235
+ Project root: '#{root}'
236
+ Application entry point: '#{fs_entrance}'
237
+ Package file name: '#{package}.tebako'#{press_announce_ref(is_msys)}
238
+ Package working directory: '#{cwd_announce}'
239
+ ANN
240
+ end
241
+
242
+ def press_announce_both
243
+ <<~ANN
244
+ Running tebako press at #{prefix}
245
+ Mode: 'both'
246
+ Ruby version: '#{@ruby_ver}'
247
+ Project root: '#{root}'
248
+ Application entry point: '#{fs_entrance}'
249
+ Runtime file name: '#{package}'
250
+ Package file name: '#{package}.tebako'
251
+ Loging level: '#{l_level}'
252
+ Package working directory: '#{cwd_announce}'
253
+ ANN
254
+ end
255
+
256
+ def press_announce_bundle
257
+ <<~ANN
258
+ Running tebako press at #{prefix}
259
+ Mode: 'bundle'
260
+ Ruby version: '#{@ruby_ver}'
261
+ Project root: '#{root}'
262
+ Application entry point: '#{fs_entrance}'
263
+ Package file name: '#{package}'
264
+ Loging level: '#{l_level}'
265
+ Package working directory: '#{cwd_announce}'
266
+ ANN
267
+ end
268
+
269
+ def press_announce_runtime
270
+ <<~ANN
271
+ Running tebako press at #{prefix}
272
+ Mode: 'runtime'
273
+ Ruby version: '#{@ruby_ver}'
274
+ Runtime file name: '#{package}'
275
+ Loging level: '#{l_level}'
276
+ ANN
277
+ end
278
+
279
+ def press_options
280
+ @press_options ||= "-DPCKG:STRING='#{package}' -DLOG_LEVEL:STRING='#{l_level}' " \
281
+ end
282
+
283
+ def process_gemfile(gemfile_path)
284
+ folder = File.dirname(gemfile_path)
285
+ filename = File.basename(gemfile_path)
286
+ # Change directory to the folder containing the Gemfile
287
+ # Because Bundler::Definition.build *sometimes* requires to be in
288
+ # the Gemfile directory
289
+ Dir.chdir(folder) do
290
+ @rv = Tebako::RubyVersionWithGemfile.new(@options["Ruby"], filename)
291
+ end
292
+ @ruby_ver, @ruby_hash = @rv.extend_ruby_version
293
+ @ruby_src_dir = nil
294
+ end
295
+
296
+ def relative?(path)
297
+ Pathname.new(path).relative?
298
+ end
299
+
300
+ def ref
301
+ @ref ||= @options["ref"].nil? ? "tebako-runtime" : @options["ref"].gsub("\\", "/")
302
+ end
303
+
304
+ def remove_glibc_private
305
+ @remove_glibc_private ||= if RUBY_PLATFORM.end_with?("linux") || RUBY_PLATFORM.end_with?("linux-gnu")
306
+ "-DREMOVE_GLIBC_PRIVATE=#{@options["patchelf"] ? "ON" : "OFF"}"
307
+ else
308
+ ""
309
+ end
310
+ end
311
+
312
+ def root
313
+ f_root = @options["root"].nil? ? "" : @options["root"].gsub("\\", "/")
314
+ @root ||= if relative?(f_root)
315
+ File.join(fs_current, f_root)
316
+ else
317
+ File.join(f_root, "")
318
+ end
319
+ end
320
+
321
+ def ruby_src_dir
322
+ @ruby_src_dir ||= File.join(deps, "src", "_ruby_#{@ruby_ver}")
323
+ end
324
+
325
+ def source
326
+ c_path = Pathname.new(__FILE__).realpath
327
+ @source ||= File.expand_path("../../..", c_path)
328
+ end
329
+
330
+ def stash_dir(rver = nil)
331
+ @stash_dir ||= "#{stash_dir_all}_#{rver || @ruby_ver}"
332
+ end
333
+
334
+ def stash_dir_all
335
+ @stash_dir_all ||= File.join(deps, "stash")
336
+ end
337
+ end
338
+ end