Module: Tebako::Codegen

Defined in:
lib/tebako/codegen.rb

Overview

Code geberation

Constant Summary collapse

COMMON_C_HEADER =
<<~SUBST
  /**
  * THIS FILE WAS GENERATED AUTOMATICALLY BY TEBAKO. DO NOT CHANGE IT, PLEASE
  **/

SUBST
COMMON_RUBY_HEADER =
<<~SUBST
  #!/usr/bin/env ruby
  # frozen_string_literal: true

  # THIS FILE WAS GENERATED AUTOMATICALLY BY TEBAKO. DO NOT CHANGE IT, PLEASE

SUBST

Class Method Summary collapse

Class Method Details

.deploy_crt_implib(opt, scm) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/tebako/codegen.rb', line 54

def deploy_crt_implib(opt, scm)
  crt = ""
  if scm.msys?
    crt = <<~SUBST
      Tebako::Packager.create_implib("#{opt.ruby_src_dir}", "#{opt.data_src_dir}",
                                     "#{opt.package}", rv)
    SUBST
  end
  crt
end

.deploy_mk(opt, scm) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/tebako/codegen.rb', line 65

def deploy_mk(opt, scm)
  case opt.mode
  when "bundle"
    deploy_mk_bundle(opt, scm)
  when /runtime|both/
    deploy_mk_stub(opt)
  end
end

.deploy_mk_bundle(opt, scm) ⇒ Object



74
75
76
77
78
79
80
81
82
83
# File 'lib/tebako/codegen.rb', line 74

def deploy_mk_bundle(opt, scm)
  <<~SUBST
    Tebako::Packager.deploy("#{opt.data_src_dir}", "#{opt.data_pre_dir}",
                            rv , "#{opt.root}", "#{scm.fs_entrance}", "#{opt.cwd}",
                            "#{opt.bundle_cache_dir}", "#{opt.native_gem_cache_dir}")
    Tebako::Packager.mkdwarfs("#{opt.deps_bin_dir}", "#{opt.data_bundle_file}",
                              "#{opt.data_src_dir}", nil, #{opt.compression_level},
                              "#{opt.filesystem_cache_dir}")
  SUBST
end

.deploy_mk_stub(opt) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/tebako/codegen.rb', line 85

def deploy_mk_stub(opt)
  <<~SUBST
    Tebako::Packager.deploy("#{opt.data_src_dir}", "#{opt.data_pre_dir}",
                            rv, "#{File.join(opt.deps, "src", "tebako", "local")}", "stub.rb", nil,
                            "#{opt.bundle_cache_dir}", "#{opt.native_gem_cache_dir}")
    Tebako::Packager.mkdwarfs("#{opt.deps_bin_dir}", "#{opt.data_stub_file}",
                              "#{opt.data_src_dir}", nil, #{opt.compression_level},
                              "#{opt.filesystem_cache_dir}")
  SUBST
end

.deploy_rb(opt, scm) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/tebako/codegen.rb', line 96

def deploy_rb(opt, scm)
  <<~SUBST
    #{deploy_rq}

    begin
      #{deploy_rb_inner(opt, scm)}
    rescue Tebako::Error => e
      puts "deploy script failed: \#{e.message} [\#{e.error_code}]"
      exit(e.error_code)
    end
  SUBST
end

.deploy_rb_inner(opt, scm) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/tebako/codegen.rb', line 109

def deploy_rb_inner(opt, scm)
  <<~SUBST
    rv = Tebako::RubyVersion.new(ARGV[0])
    stash = File.join("#{opt.deps}", "stash_\#{ARGV[0]}")
    Tebako::Packager::init(stash.to_s, "#{opt.data_src_dir}",
                         "#{opt.data_pre_dir}", "#{opt.data_bin_dir}")
    #{deploy_crt_implib(opt, scm)}
    #{deploy_mk(opt, scm)}
  SUBST
end

.deploy_rqObject



120
121
122
123
124
125
126
127
# File 'lib/tebako/codegen.rb', line 120

def deploy_rq
  <<~SUBST
    require "#{File.join(__dir__, "error.rb")}"
    require "#{File.join(__dir__, "package_descriptor.rb")}"
    require "#{File.join(__dir__, "packager.rb")}"
    require "#{File.join(__dir__, "ruby_version.rb")}"
  SUBST
end

.generate_deploy_rb(options_manager, scenario_manager) ⇒ Object



144
145
146
147
148
149
# File 'lib/tebako/codegen.rb', line 144

def generate_deploy_rb(options_manager, scenario_manager)
  puts "   ... deploy.rb"

  fname = File.join(options_manager.deps, "bin", "deploy.rb")
  write_file(fname, COMMON_RUBY_HEADER + deploy_rb(options_manager, scenario_manager))
end

.generate_package_descriptor(options_manager, scenario_manager, mount_point: scenario_manager.fs_mount_point) ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'lib/tebako/codegen.rb', line 151

def generate_package_descriptor(options_manager, scenario_manager, mount_point: scenario_manager.fs_mount_point)
  puts "   ... package_descriptor"
  fname = File.join(options_manager.deps, "src", "tebako", "package_descriptor")
  descriptor = Tebako::PackageDescriptor.new(options_manager.ruby_ver, Tebako::VERSION,
                                             mount_point, scenario_manager.fs_entry_point,
                                             options_manager.cwd)
  write_file(fname, descriptor.serialize, binary: true)
  fname
end

.generate_package_manifest(options_manager, scenario_manager) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/tebako/codegen.rb', line 175

def generate_package_manifest(options_manager, scenario_manager)
  puts "   ... package.manifest"

  root = package_manifest_root(options_manager)
   = (options_manager, scenario_manager)
  content = Tebako::ContentManifest.serialize(
    root: root,
    metadata: ,
    excluded: package_manifest_exclusions(root, options_manager)
  )
  write_file(options_manager.package_manifest, content)
end

.generate_stub_rb(options_manager) ⇒ Object



137
138
139
140
141
142
# File 'lib/tebako/codegen.rb', line 137

def generate_stub_rb(options_manager)
  puts "   ... stub.rb"

  fname = File.join(options_manager.deps, "src", "tebako", "local", "stub.rb")
  write_file(fname, COMMON_RUBY_HEADER + stub_rb(options_manager))
end

.generate_tebako_fs_cpp(options_manager, scenario_manager) ⇒ Object



161
162
163
164
165
166
# File 'lib/tebako/codegen.rb', line 161

def generate_tebako_fs_cpp(options_manager, scenario_manager)
  puts "   ... tebako-fs.cpp"

  fname = File.join(options_manager.deps, "src", "tebako", "tebako-fs.cpp")
  write_file(fname, COMMON_C_HEADER + tebako_fs_cpp(options_manager, scenario_manager))
end

.generate_tebako_version_h(options_manager, v_parts) ⇒ Object



168
169
170
171
172
173
# File 'lib/tebako/codegen.rb', line 168

def generate_tebako_version_h(options_manager, v_parts)
  puts "   ... tebako-version.h"

  fname = File.join(options_manager.deps, "include", "tebako", "tebako-version.h")
  write_file(fname, COMMON_C_HEADER + tebako_version_h(v_parts))
end

.package_cwd(options_manager, scenario_manager) ⇒ Object



220
221
222
223
224
225
226
# File 'lib/tebako/codegen.rb', line 220

def package_cwd(options_manager, scenario_manager)
  if options_manager.cwd.nil?
    "nullptr"
  else
    "\"#{scenario_manager.fs_mount_point}/#{options_manager.cwd}\""
  end
end

.package_manifest_exclusions(root, options_manager) ⇒ Object



204
205
206
207
208
209
210
# File 'lib/tebako/codegen.rb', line 204

def package_manifest_exclusions(root, options_manager)
  root = File.expand_path(root)
  [options_manager.prefix, options_manager.package].compact.filter_map do |path|
    expanded = File.expand_path(path)
    expanded if expanded != root && expanded.start_with?("#{root}#{File::SEPARATOR}")
  end
end

.package_manifest_metadata(options_manager, scenario_manager) ⇒ Object



194
195
196
197
198
199
200
201
202
# File 'lib/tebako/codegen.rb', line 194

def (options_manager, scenario_manager)
  {
    compression_level: options_manager.compression_level,
    entry_point: options_manager.mode == "bundle" ? scenario_manager.fs_entrance : "stub.rb",
    mode: options_manager.mode == "bundle" ? "bundle" : "runtime",
    ruby_version: options_manager.ruby_ver,
    tebako_version: Tebako::VERSION
  }
end

.package_manifest_root(options_manager) ⇒ Object



188
189
190
191
192
# File 'lib/tebako/codegen.rb', line 188

def package_manifest_root(options_manager)
  return options_manager.root if options_manager.mode == "bundle"

  File.join(options_manager.deps, "src", "tebako", "local")
end

.stub_rb(opt) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/tebako/codegen.rb', line 129

def stub_rb(opt)
  <<~SUBST
    puts "Copyright (c) 2024-2025 Ribose Inc (https://www.ribose.com)"
    puts "Tebako runtime stub v#{Tebako::VERSION}"
    puts "To run your application please call #{File.basename(opt.package)} --tebako-run <your tebako package>"
  SUBST
end

.tebako_fs_cpp(options_manager, scenario_manager) ⇒ Object



228
229
230
231
232
233
234
235
# File 'lib/tebako/codegen.rb', line 228

def tebako_fs_cpp(options_manager, scenario_manager)
  case options_manager.mode
  when "bundle"
    tebako_fs_cpp_bundle(options_manager, scenario_manager)
  when /runtime|both/
    tebako_fs_cpp_stub(options_manager, scenario_manager)
  end
end

.tebako_fs_cpp_bundle(options_manager, scenario_manager) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/tebako/codegen.rb', line 237

def tebako_fs_cpp_bundle(options_manager, scenario_manager)
  <<~SUBST
    #include <limits.h>
    #include <incbin/incbin.h>

    namespace tebako {
      const  char * fs_log_level   = "#{options_manager.l_level}";
      const  char * fs_mount_point = "#{scenario_manager.fs_mount_point}";
      const  char * fs_entry_point = "#{scenario_manager.fs_entry_point}";
      const  char * package_cwd 	 = #{package_cwd(options_manager, scenario_manager)};
      char   original_cwd[PATH_MAX];

      INCBIN(fs, "#{options_manager.data_bundle_file}");
    }
  SUBST
end

.tebako_fs_cpp_stub(options_manager, scenario_manager) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/tebako/codegen.rb', line 254

def tebako_fs_cpp_stub(options_manager, scenario_manager)
  <<~SUBST
    #include <limits.h>
    #include <incbin/incbin.h>

    namespace tebako {
      const  char * fs_log_level   = "#{options_manager.l_level}";
      const  char * fs_mount_point = "#{scenario_manager.fs_mount_point}";
      const  char * fs_entry_point = "/local/stub.rb";
      const  char * package_cwd 	 = nullptr;
      char   original_cwd[PATH_MAX];

      INCBIN(fs, "#{options_manager.data_stub_file}");
    }
  SUBST
end

.tebako_version_h(v_parts) ⇒ Object



271
272
273
274
275
276
277
278
279
# File 'lib/tebako/codegen.rb', line 271

def tebako_version_h(v_parts)
  <<~SUBST
    #pragma once

    const unsigned int tebako_version_major = #{v_parts[0]};
    const unsigned int tebako_version_minor = #{v_parts[1]};
    const unsigned int tebako_version_teeny = #{v_parts[2]};
  SUBST
end

.write_file(path, content, binary: false) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/tebako/codegen.rb', line 212

def write_file(path, content, binary: false)
  FileUtils.mkdir_p(File.dirname(path))
  return path if File.exist?(path) && File.binread(path) == content

  binary ? File.binwrite(path, content) : File.write(path, content)
  path
end