Skip to content

Commit 58dfafe

Browse files
committed
feat: bundle t-ruby source at build time
- Add bundle-t-ruby.mjs script to embed Ruby source files - Update release workflow to clone t-ruby and bundle sources - Support dynamic init script generation based on bundle availability - Add vendor/ to gitignore (populated during CI build)
1 parent b62fbd1 commit 58dfafe

File tree

6 files changed

+199
-7
lines changed

6 files changed

+199
-7
lines changed

.github/workflows/release.yml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,29 @@ jobs:
4141
VERSION=${GITHUB_REF#refs/tags/v}
4242
T_RUBY_VERSION=""
4343
fi
44+
# t_ruby_version이 없으면 version과 동일하게 설정
45+
if [[ -z "$T_RUBY_VERSION" ]]; then
46+
T_RUBY_VERSION="$VERSION"
47+
fi
4448
echo "version=$VERSION" >> $GITHUB_OUTPUT
4549
echo "t_ruby_version=$T_RUBY_VERSION" >> $GITHUB_OUTPUT
46-
echo "Publishing version: $VERSION"
50+
echo "Publishing version: $VERSION (t-ruby: $T_RUBY_VERSION)"
51+
52+
- name: Clone t-ruby source
53+
run: |
54+
git clone --depth 1 --branch v${{ steps.version.outputs.t_ruby_version }} \
55+
https://github.com/type-ruby/t-ruby.git /tmp/t-ruby
56+
echo "Cloned t-ruby v${{ steps.version.outputs.t_ruby_version }}"
57+
58+
- name: Copy t-ruby lib to vendor
59+
run: |
60+
mkdir -p vendor/t-ruby
61+
cp -r /tmp/t-ruby/lib/* vendor/t-ruby/
62+
echo "Copied t-ruby lib files:"
63+
ls -la vendor/t-ruby/
64+
65+
- name: Bundle t-ruby source
66+
run: node scripts/bundle-t-ruby.mjs
4767

4868
- name: Build
4969
run: npm run build

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ node_modules/
44
# Build output
55
dist/
66

7+
# Vendor (t-ruby source copied during CI build)
8+
vendor/
9+
710
# IDE
811
.idea/
912
.vscode/

scripts/bundle-t-ruby.mjs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Bundle T-Ruby source files into a TypeScript module
5+
*
6+
* This script reads all Ruby files from vendor/t-ruby and generates
7+
* a TypeScript file that embeds them for use in the WASM environment.
8+
*/
9+
10+
import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "node:fs";
11+
import { dirname, join, relative } from "node:path";
12+
import { fileURLToPath } from "node:url";
13+
14+
const __dirname = dirname(fileURLToPath(import.meta.url));
15+
const rootDir = join(__dirname, "..");
16+
const vendorDir = join(rootDir, "vendor", "t-ruby");
17+
const outputFile = join(rootDir, "src", "vm", "TRubyBundle.ts");
18+
19+
/**
20+
* Recursively collect all .rb files from a directory
21+
*/
22+
function collectRubyFiles(dir, basePath = "") {
23+
const files = [];
24+
25+
if (!existsSync(dir)) {
26+
return files;
27+
}
28+
29+
for (const entry of readdirSync(dir)) {
30+
const fullPath = join(dir, entry);
31+
const relativePath = basePath ? `${basePath}/${entry}` : entry;
32+
33+
if (statSync(fullPath).isDirectory()) {
34+
files.push(...collectRubyFiles(fullPath, relativePath));
35+
} else if (entry.endsWith(".rb")) {
36+
files.push({
37+
path: relativePath,
38+
content: readFileSync(fullPath, "utf-8"),
39+
});
40+
}
41+
}
42+
43+
return files;
44+
}
45+
46+
/**
47+
* Escape string for use in TypeScript template literal
48+
*/
49+
function escapeForTemplate(str) {
50+
return str
51+
.replace(/\\/g, "\\\\")
52+
.replace(/`/g, "\\`")
53+
.replace(/\$\{/g, "\\${");
54+
}
55+
56+
console.log("Bundling T-Ruby source files...");
57+
58+
const files = collectRubyFiles(vendorDir);
59+
60+
if (files.length === 0) {
61+
console.log("No Ruby files found in vendor/t-ruby. Using fallback bundle.");
62+
63+
// Generate fallback bundle (minimal implementation)
64+
const fallbackContent = `/**
65+
* T-Ruby Bundle - Auto-generated
66+
*
67+
* This file contains bundled T-Ruby source files for WASM environment.
68+
* Generated at build time from vendor/t-ruby directory.
69+
*
70+
* @internal
71+
*/
72+
73+
/** Bundled T-Ruby source files */
74+
export const T_RUBY_BUNDLE: Record<string, string> = {};
75+
76+
/** Flag indicating if real T-Ruby is bundled */
77+
export const HAS_T_RUBY_BUNDLE = false;
78+
`;
79+
80+
writeFileSync(outputFile, fallbackContent);
81+
console.log("Generated fallback bundle.");
82+
} else {
83+
console.log(`Found ${files.length} Ruby files to bundle.`);
84+
85+
// Generate TypeScript bundle
86+
let content = `/**
87+
* T-Ruby Bundle - Auto-generated
88+
*
89+
* This file contains bundled T-Ruby source files for WASM environment.
90+
* Generated at build time from vendor/t-ruby directory.
91+
*
92+
* DO NOT EDIT MANUALLY - This file is auto-generated by scripts/bundle-t-ruby.mjs
93+
*
94+
* @internal
95+
*/
96+
97+
/** Bundled T-Ruby source files */
98+
export const T_RUBY_BUNDLE: Record<string, string> = {
99+
`;
100+
101+
for (const file of files) {
102+
content += ` "${file.path}": \`${escapeForTemplate(file.content)}\`,\n`;
103+
}
104+
105+
content += `};
106+
107+
/** Flag indicating if real T-Ruby is bundled */
108+
export const HAS_T_RUBY_BUNDLE = true;
109+
`;
110+
111+
writeFileSync(outputFile, content);
112+
console.log(`Generated bundle with ${files.length} files: ${outputFile}`);
113+
}

src/vm/TRubyBundle.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* T-Ruby Bundle - Auto-generated
3+
*
4+
* This file contains bundled T-Ruby source files for WASM environment.
5+
* Generated at build time from vendor/t-ruby directory.
6+
*
7+
* @internal
8+
*/
9+
10+
/** Bundled T-Ruby source files */
11+
export const T_RUBY_BUNDLE: Record<string, string> = {};
12+
13+
/** Flag indicating if real T-Ruby is bundled */
14+
export const HAS_T_RUBY_BUNDLE = false;

src/vm/TRubyInitScript.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,49 @@
1+
import { T_RUBY_BUNDLE, HAS_T_RUBY_BUNDLE } from "./TRubyBundle.js";
2+
13
/**
2-
* Ruby initialization script for T-Ruby in WASM environment
4+
* Generate Ruby initialization script for T-Ruby in WASM environment
35
*
46
* @remarks
5-
* This script is executed when the Ruby VM is initialized.
6-
* It attempts to load the T-Ruby gem, and falls back to a minimal
7-
* implementation if the gem is not available.
7+
* This function generates a script that either loads bundled T-Ruby files
8+
* or falls back to a minimal implementation if no bundle is available.
89
*
910
* @internal
1011
*/
11-
export const T_RUBY_INIT_SCRIPT = `
12+
export function generateInitScript(): string {
13+
if (HAS_T_RUBY_BUNDLE) {
14+
// Generate script that loads bundled files
15+
let script = `
16+
# T-Ruby WASM Bundle Loader
17+
$LOAD_PATH.unshift('/t-ruby')
18+
19+
# Create virtual file system for bundled files
20+
`;
21+
22+
// Add each bundled file to the virtual file system
23+
for (const [path, content] of Object.entries(T_RUBY_BUNDLE)) {
24+
const escapedContent = content
25+
.replace(/\\/g, "\\\\")
26+
.replace(/'/g, "\\'")
27+
.replace(/\n/g, "\\n");
28+
script += `
29+
begin
30+
dir = File.dirname('/t-ruby/${path}')
31+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
32+
rescue; end
33+
File.write('/t-ruby/${path}', '${escapedContent}')
34+
`;
35+
}
36+
37+
script += `
38+
require 'rubygems'
39+
require 't_ruby'
40+
`;
41+
42+
return script;
43+
}
44+
45+
// Fallback: minimal implementation
46+
return `
1247
require 'rubygems'
1348
begin
1449
require 't-ruby'
@@ -36,3 +71,9 @@ rescue LoadError
3671
end
3772
end
3873
`;
74+
}
75+
76+
/**
77+
* @deprecated Use generateInitScript() instead
78+
*/
79+
export const T_RUBY_INIT_SCRIPT = generateInitScript();

src/vm/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55

66
export type { RubyVM } from "./RubyVM.js";
77
export type { DefaultRubyVMResult } from "./DefaultRubyVM.js";
8-
export { T_RUBY_INIT_SCRIPT } from "./TRubyInitScript.js";
8+
export { T_RUBY_INIT_SCRIPT, generateInitScript } from "./TRubyInitScript.js";
9+
export { T_RUBY_BUNDLE, HAS_T_RUBY_BUNDLE } from "./TRubyBundle.js";

0 commit comments

Comments
 (0)