jarbler 0.1.8 → 0.2.1
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +15 -13
- data/jarbler.gemspec +1 -1
- data/lib/jarbler/JarMain.java +9 -2
- data/lib/jarbler/builder.rb +42 -7
- data/lib/jarbler/config.rb +35 -10
- data/lib/jarbler/version.rb +2 -2
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 97f5261d55e15e23454414413af5f467bfdf5c2554916574269d6fa99f4a411a
|
|
4
|
+
data.tar.gz: 5a77de393585a7fa444157ebc2e7835d6d39e2e0e004ade0f840d9f2f9abcff9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad30f274db2a26f844df82f295b95f9bdcd9a023f35bbc83a6d2b7ec44b77a4dd0b8ca5ca66bb3f46818acf927d2e72efefb0f8b2669b058f5f51b9dacdb6d49
|
|
7
|
+
data.tar.gz: e07c531aa6082b3d186d2d3687d6a784b9b07593f4145e4d51bdd28247f57c710a35ed15196c18a0d3cb5a9f503808b242833709780b71442e0f293de1fe0db4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - 2024-06-13
|
|
4
|
+
|
|
5
|
+
- Ruby files remain originally in jar if compile fails for a single file.
|
|
6
|
+
- Gems are compiled only if include_gems_to_compile=true
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2024-06-12
|
|
9
|
+
|
|
10
|
+
- Add ahead of time compilation support for JRuby
|
|
11
|
+
|
|
3
12
|
## [0.1.6] - 2023-06-19
|
|
4
13
|
|
|
5
14
|
- Bugfix: Do not clone default gems, because they are already included in the jruby jars standard library
|
data/README.md
CHANGED
|
@@ -4,8 +4,8 @@ Pack a Ruby application into an executable jar file.
|
|
|
4
4
|
|
|
5
5
|
Jarbler creates a self executing Java jar file containing a Ruby application and all its Gem dependencies.
|
|
6
6
|
|
|
7
|
-
This tool is inspired by the widely used
|
|
8
|
-
The configured Ruby program is directly executed inside the JVM using the
|
|
7
|
+
This tool is inspired by the widely used JRuby runner Warbler.
|
|
8
|
+
The configured Ruby program is directly executed inside the JVM using the JRuby runtime jars.
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
@@ -31,7 +31,7 @@ To adjust Jarbler's configuration, modify the settings in config file ´config/j
|
|
|
31
31
|
|
|
32
32
|
### Preconditions
|
|
33
33
|
* Dependency handling should be based on Bundler (existence of Gemfile is required)
|
|
34
|
-
* The Ruby app should be capable of running with
|
|
34
|
+
* The Ruby app should be capable of running with JRuby
|
|
35
35
|
* Gems with native extensions should not be used (e.g. sassc)
|
|
36
36
|
* if needed for development or test such Gems with native extensions should be moved to the development and test group in the Gemfile.
|
|
37
37
|
* Otherwise the created jar file may not be executable on all platforms and Java versions.
|
|
@@ -50,22 +50,24 @@ To create a template config file with information about all the supported config
|
|
|
50
50
|
|
|
51
51
|
$ jarble config
|
|
52
52
|
|
|
53
|
-
The default configuration
|
|
53
|
+
The default configuration is focused on Ruby on Rails applications.<br>
|
|
54
54
|
|
|
55
55
|
### Configuration options
|
|
56
|
-
| Option
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
56
|
+
| Option | Default value | Description |
|
|
57
|
+
|-------------------------|--------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
58
|
+
| compile_ruby_files | false | Ahead of time compilation of all .rb files of application and Gem dependencies to .class files. Only store .class files in jar. Requires JRuby runtime. |
|
|
59
|
+
| executable | "bin/rails" | The ruby start file to run at execution of jar file. File extension .class is used automatically if start file is .rb and AOT compilation is used. |
|
|
60
|
+
| executable_params | ["server", "-e", "production", "-p", "8080"] | Command line parameters to be used for the ruby executable |
|
|
61
|
+
| excludes | ["tmp/cache", "tmp/pids", ...] (see generated template file for whole content) | The files and dirs of the project to exlude from the include option |
|
|
62
|
+
| include_gems_to_compile | false | Should .rb files of the project gems also be compiled if compile_ruby_files = true |
|
|
63
|
+
| includes | ["app", "bin", "config", ...] (see generated template file for whole content) | The files and dirs of the project to include in the jar file |
|
|
64
|
+
| jar_name | < Name of project dir >.jar | The name of the generated jar file |
|
|
65
|
+
| jruby_version | The current most recent JRuby version | The version of the JRuby runtime to use |
|
|
64
66
|
|
|
65
67
|
|
|
66
68
|
## Troubleshooting
|
|
67
69
|
* Set DEBUG=true in environment to get additional runtime information
|
|
68
|
-
* The temporary folder with the extracted app and
|
|
70
|
+
* The temporary folder with the extracted app and JRuby runtime files is not deleted after execution if DEBUG is set.
|
|
69
71
|
|
|
70
72
|
### Possible error messages
|
|
71
73
|
* Gem::LoadError: You have already activated ..., but your Gemfile requires ... . Since ... is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports net-protocol as a default gem.
|
data/jarbler.gemspec
CHANGED
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.email = ["Peter@ramm-oberhermsdorf.de"]
|
|
10
10
|
|
|
11
11
|
spec.summary = "Pack a Ruby app into a Java jar file"
|
|
12
|
-
spec.description = "Pack a Ruby app combined with
|
|
12
|
+
spec.description = "Pack a Ruby app combined with JRuby runtime and all its Gem dependencies into a jar file to simply run the app on any Java platform by '> java -jar file.jar'"
|
|
13
13
|
spec.homepage = "https://github.com/rammpeter/jarbler"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
spec.required_ruby_version = ">= 2.6.0"
|
data/lib/jarbler/JarMain.java
CHANGED
|
@@ -87,6 +87,13 @@ class JarMain {
|
|
|
87
87
|
executable = prop.getProperty("jarbler.executable");
|
|
88
88
|
executable_params = prop.getProperty("jarbler.executable_params");
|
|
89
89
|
|
|
90
|
+
Boolean compile_ruby_files = Boolean.parseBoolean(prop.getProperty("jarbler.compile_ruby_files", "false"));
|
|
91
|
+
if (compile_ruby_files) {
|
|
92
|
+
debug("Set system property jruby.aot.loadClasses = true");
|
|
93
|
+
// ensure that .class files are loaded at require time if rb files are not present
|
|
94
|
+
System.setProperty("jruby.aot.loadClasses", "true");
|
|
95
|
+
}
|
|
96
|
+
|
|
90
97
|
// throw exception if executable is null
|
|
91
98
|
if (executable == null) {
|
|
92
99
|
throw new RuntimeException("Property 'executable' definition missing in jarbler.properties");
|
|
@@ -129,12 +136,12 @@ class JarMain {
|
|
|
129
136
|
}
|
|
130
137
|
}
|
|
131
138
|
|
|
132
|
-
debug("
|
|
139
|
+
debug("JRuby program starts with the following arguments: ");
|
|
133
140
|
for (String arg : mainArgs) {
|
|
134
141
|
debug(" - " + arg);
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
debug("
|
|
144
|
+
debug("JRuby set property 'user.dir' to '" + app_root + "'");
|
|
138
145
|
System.setProperty("user.dir", app_root);
|
|
139
146
|
// call the method org.jruby.Main.main
|
|
140
147
|
debug("Calling org.jruby.Main.main with: "+ mainArgs);
|
data/lib/jarbler/builder.rb
CHANGED
|
@@ -49,6 +49,7 @@ module Jarbler
|
|
|
49
49
|
java_executable_params += "#{param} "
|
|
50
50
|
end
|
|
51
51
|
file.write("jarbler.executable_params=#{java_executable_params.strip}\n")
|
|
52
|
+
file.write("jarbler.compile_ruby_files=#{config.compile_ruby_files}\n")
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
# remove files and directories from excludes, if they exist (after copying the rails project and the gems)
|
|
@@ -62,6 +63,8 @@ module Jarbler
|
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
|
|
66
|
+
compile_ruby_files if config.compile_ruby_files
|
|
67
|
+
|
|
65
68
|
exec_command "jar cfm #{config.jar_name} Manifest.txt *" # create the jar file
|
|
66
69
|
|
|
67
70
|
# place the jar in project directory
|
|
@@ -202,7 +205,7 @@ module Jarbler
|
|
|
202
205
|
|
|
203
206
|
# Copy the jruby-jars to the staging directory
|
|
204
207
|
# @param [String] staging_dir Path to the staging directory
|
|
205
|
-
# @return [String] the minor ruby version of the
|
|
208
|
+
# @return [String] the minor ruby version of the JRuby jars with patch level set to 0
|
|
206
209
|
def copy_jruby_jars_to_staging(staging_dir)
|
|
207
210
|
|
|
208
211
|
# Ensure that jruby-jars gem is installed, otherwise install it. Accepts also bundler path in .bundle/config
|
|
@@ -211,7 +214,7 @@ module Jarbler
|
|
|
211
214
|
raise "jruby-jars gem not installed in version #{config.jruby_version}" if installed.empty?
|
|
212
215
|
|
|
213
216
|
jruby_jars_location = installed[0]&.full_gem_path
|
|
214
|
-
debug "
|
|
217
|
+
debug "JRuby jars installed at: #{jruby_jars_location}"
|
|
215
218
|
|
|
216
219
|
# Get the location of the jruby-jars gem
|
|
217
220
|
# spec = Gem::Specification.find_by_name('jruby-jars', config.jruby_version)
|
|
@@ -220,14 +223,14 @@ module Jarbler
|
|
|
220
223
|
file_utils_copy("#{jruby_jars_location}/lib/jruby-core-#{config.jruby_version}-complete.jar", staging_dir)
|
|
221
224
|
file_utils_copy("#{jruby_jars_location}/lib/jruby-stdlib-#{config.jruby_version}.jar", staging_dir)
|
|
222
225
|
|
|
223
|
-
# Get the according Ruby version for the current
|
|
226
|
+
# Get the according Ruby version for the current JRuby version
|
|
224
227
|
lines = exec_command "java -cp #{jruby_jars_location}/lib/jruby-core-#{config.jruby_version}-complete.jar org.jruby.Main --version"
|
|
225
228
|
match_result = lines.match(/\(.*\)/)
|
|
226
|
-
raise "Could not determine Ruby version for
|
|
229
|
+
raise "Could not determine Ruby version for JRuby #{config.jruby_version} in following output:\n#{lines}" unless match_result
|
|
227
230
|
ruby_version = match_result[0].tr('()', '')
|
|
228
|
-
debug "Corresponding Ruby version for
|
|
231
|
+
debug "Corresponding Ruby version for JRuby (#{config.jruby_version}): #{ruby_version}"
|
|
229
232
|
ruby_minor_version = ruby_version.split('.')[0..1].join('.') + '.0'
|
|
230
|
-
debug "Corresponding Ruby minor version for
|
|
233
|
+
debug "Corresponding Ruby minor version for JRuby (#{config.jruby_version}): #{ruby_minor_version}"
|
|
231
234
|
ruby_minor_version
|
|
232
235
|
end
|
|
233
236
|
|
|
@@ -255,6 +258,38 @@ module Jarbler
|
|
|
255
258
|
puts "Error copying #{source} to #{destination}"
|
|
256
259
|
raise
|
|
257
260
|
end
|
|
258
|
-
end
|
|
259
261
|
|
|
262
|
+
# Compile all Ruby files in the current directory (staging directory)
|
|
263
|
+
def compile_ruby_files
|
|
264
|
+
require 'jruby/jrubyc'
|
|
265
|
+
|
|
266
|
+
puts "Compiling all .rb files to .class files"
|
|
267
|
+
# Inform if used JRuby version is different from the intended runtime JRuby version
|
|
268
|
+
if JRUBY_VERSION != config.jruby_version
|
|
269
|
+
puts "Compiling .rb files to .class is done with JRuby version #{JRUBY_VERSION}, but intended runtime JRuby version for jar file is #{config.jruby_version}"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
ruby_files = Find.find('.').select { |f| f =~ /\.rb$/ } # find all Ruby files in the current directory
|
|
273
|
+
|
|
274
|
+
if !config.include_gems_to_compile
|
|
275
|
+
ruby_files = ruby_files.select { |f| !(f =~ /\.#{File::SEPARATOR}gems#{File::SEPARATOR}/) } # Exclude ./gems/* directories from compiling
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
ruby_files.each do |ruby_file|
|
|
279
|
+
debug "Compile Ruby file #{ruby_file}"
|
|
280
|
+
full_file_name = File.join(Dir.pwd, ruby_file) # full name including path is required by the JRuby compiler
|
|
281
|
+
begin
|
|
282
|
+
status = JRuby::Compiler::compile_argv([full_file_name]) # compile the Ruby file
|
|
283
|
+
if status == 0
|
|
284
|
+
File.delete(full_file_name) # remove the original Ruby file to ensure that the compiled class file is used
|
|
285
|
+
else
|
|
286
|
+
raise "Return status != 0"
|
|
287
|
+
end
|
|
288
|
+
rescue Exception => e
|
|
289
|
+
puts "Error compiling Ruby file '#{ruby_file}': #{e.class}:#{e.message}"
|
|
290
|
+
puts "'#{ruby_file}' is not compiled and will be included in the jar file as original Ruby file"
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
260
295
|
end
|
data/lib/jarbler/config.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'json'
|
|
|
3
3
|
|
|
4
4
|
module Jarbler
|
|
5
5
|
class Config
|
|
6
|
-
attr_accessor :jar_name, :includes, :excludes, :jruby_version, :executable, :executable_params
|
|
6
|
+
attr_accessor :jar_name, :includes, :excludes, :jruby_version, :executable, :executable_params, :compile_ruby_files, :include_gems_to_compile
|
|
7
7
|
|
|
8
8
|
CONFIG_FILE = 'config/jarble.rb'
|
|
9
9
|
# create instance of Config class with defaults or from config file
|
|
@@ -19,16 +19,22 @@ module Jarbler
|
|
|
19
19
|
config = Config.new
|
|
20
20
|
end
|
|
21
21
|
config.define_jruby_version
|
|
22
|
+
# Replace .rb with .class if compile_ruby_files is true
|
|
23
|
+
config.executable = config.executable.sub(/\.rb$/, '.class') if config.compile_ruby_files
|
|
24
|
+
|
|
25
|
+
config.validate_values
|
|
22
26
|
config
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def initialize
|
|
26
|
-
@
|
|
27
|
-
@includes = %w(app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile script vendor tmp)
|
|
30
|
+
@compile_ruby_files = false
|
|
28
31
|
@excludes = %w(tmp/cache tmp/pids tmp/sockets vendor/bundle vendor/cache vendor/ruby)
|
|
29
|
-
@jruby_version = nil # determined automatically at runtime
|
|
30
32
|
@executable = 'bin/rails'
|
|
31
33
|
@executable_params = %w(server -e production -p 8080)
|
|
34
|
+
@include_gems_to_compile = false
|
|
35
|
+
@includes = %w(app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile script vendor tmp)
|
|
36
|
+
@jar_name = File.basename(Dir.pwd) + '.jar'
|
|
37
|
+
@jruby_version = nil # determined automatically at runtime
|
|
32
38
|
# execute additional block if given
|
|
33
39
|
yield self if block_given?
|
|
34
40
|
end
|
|
@@ -47,9 +53,9 @@ module Jarbler
|
|
|
47
53
|
# config.excludes = #{excludes}
|
|
48
54
|
# config.excludes << 'additional'
|
|
49
55
|
|
|
50
|
-
# Use
|
|
56
|
+
# Use certain JRuby version
|
|
51
57
|
# if not set (nil) then the version defined in .ruby-version
|
|
52
|
-
# if not
|
|
58
|
+
# if not JRuby version defined here or in .ruby-version then the latest available JRuby version is used
|
|
53
59
|
# config.jruby_version = '9.2.3.0'
|
|
54
60
|
# config.jruby_version = nil
|
|
55
61
|
|
|
@@ -58,6 +64,14 @@ module Jarbler
|
|
|
58
64
|
|
|
59
65
|
# Additional command line parameters for the Ruby executable
|
|
60
66
|
# config.executable_params = #{executable_params}
|
|
67
|
+
|
|
68
|
+
# Compile the ruby files of the project to Java .class files with JRuby's ahead-of-time compiler?
|
|
69
|
+
# the original ruby files are not included in the jar file, so source code is not visible
|
|
70
|
+
# config.compile_ruby_files = #{compile_ruby_files}
|
|
71
|
+
|
|
72
|
+
# Compile also the .rb files of the gems of the project to Java .class files?
|
|
73
|
+
# config.include_gems_to_compile = #{include_gems_to_compile}
|
|
74
|
+
|
|
61
75
|
".split("\n"))
|
|
62
76
|
end
|
|
63
77
|
|
|
@@ -83,15 +97,15 @@ module Jarbler
|
|
|
83
97
|
puts "Jarbler: Created config file #{Dir.pwd}/#{CONFIG_FILE}"
|
|
84
98
|
end
|
|
85
99
|
|
|
86
|
-
# define
|
|
100
|
+
# define JRuby version if not set in config file
|
|
87
101
|
def define_jruby_version
|
|
88
102
|
unless @jruby_version # not defined in config file
|
|
89
103
|
if File.exist?('.ruby-version')
|
|
90
104
|
# read the file RAILS_ROOT/.ruby-version starting from char at position 6 to the end of the line
|
|
91
105
|
self.jruby_version = File.read('.ruby-version')[6..20].strip
|
|
92
|
-
debug "
|
|
106
|
+
debug "JRuby version from .ruby-version file: #{jruby_version}"
|
|
93
107
|
else
|
|
94
|
-
# no .ruby-version file, use
|
|
108
|
+
# no .ruby-version file, use JRuby version of the latest Gem
|
|
95
109
|
# Fetch the gem specification from Rubygems.org
|
|
96
110
|
# search for the gem and get the JSON response
|
|
97
111
|
response = Gem::SpecFetcher.fetcher.search_for_dependency(Gem::Dependency.new('jruby-jars'))
|
|
@@ -105,7 +119,7 @@ module Jarbler
|
|
|
105
119
|
#jruby_jars_line = lines.match(/^jruby-jars \((.*)\)/)
|
|
106
120
|
#raise "No jruby-jars gem found in rubygems.org!" unless jruby_jars_line
|
|
107
121
|
#self.jruby_version = /\((.*?)\)/.match(jruby_jars_line.to_s)[1]
|
|
108
|
-
debug "
|
|
122
|
+
debug "JRuby version from latest jruby-jars gem: #{jruby_version}"
|
|
109
123
|
end
|
|
110
124
|
end
|
|
111
125
|
end
|
|
@@ -113,5 +127,16 @@ module Jarbler
|
|
|
113
127
|
def debug(msg)
|
|
114
128
|
puts msg if ENV['DEBUG']
|
|
115
129
|
end
|
|
130
|
+
|
|
131
|
+
def validate_values
|
|
132
|
+
raise "Invalid config value for jar name: #{jar_name}" unless jar_name =~ /\w+/
|
|
133
|
+
raise "Invalid config value for executable: #{executable}" unless executable =~ /\w+/
|
|
134
|
+
raise "Invalid config value for executable params: #{executable_params}" unless executable_params.is_a?(Array)
|
|
135
|
+
raise "Invalid config value for includes: #{includes}" unless includes.is_a?(Array)
|
|
136
|
+
raise "Invalid config value for excludes: #{excludes}" unless excludes.is_a?(Array)
|
|
137
|
+
raise "Invalid config value for compile_ruby_files: #{compile_ruby_files}" unless [true, false].include?(compile_ruby_files)
|
|
138
|
+
raise "compile_ruby_files = true is supported only with JRuby! Current runtime is '#{RUBY_ENGINE}'" if compile_ruby_files && (defined?(RUBY_ENGINE) && RUBY_ENGINE != 'jruby')
|
|
139
|
+
raise "include_gems_to_compile = true is supported only if compile_ruby_files = true!" if include_gems_to_compile && !compile_ruby_files
|
|
140
|
+
end
|
|
116
141
|
end
|
|
117
142
|
end
|
data/lib/jarbler/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jarbler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter Ramm
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-06-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description: Pack a Ruby app combined with
|
|
13
|
+
description: Pack a Ruby app combined with JRuby runtime and all its Gem dependencies
|
|
14
14
|
into a jar file to simply run the app on any Java platform by '> java -jar file.jar'
|
|
15
15
|
email:
|
|
16
16
|
- Peter@ramm-oberhermsdorf.de
|
|
@@ -42,7 +42,7 @@ metadata:
|
|
|
42
42
|
homepage_uri: https://github.com/rammpeter/jarbler
|
|
43
43
|
source_code_uri: https://github.com/rammpeter/jarbler
|
|
44
44
|
changelog_uri: https://github.com/rammpeter/jarbler/CHANGELOG.md
|
|
45
|
-
post_install_message:
|
|
45
|
+
post_install_message:
|
|
46
46
|
rdoc_options: []
|
|
47
47
|
require_paths:
|
|
48
48
|
- lib
|
|
@@ -57,8 +57,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
57
57
|
- !ruby/object:Gem::Version
|
|
58
58
|
version: '0'
|
|
59
59
|
requirements: []
|
|
60
|
-
rubygems_version: 3.
|
|
61
|
-
signing_key:
|
|
60
|
+
rubygems_version: 3.3.27
|
|
61
|
+
signing_key:
|
|
62
62
|
specification_version: 4
|
|
63
63
|
summary: Pack a Ruby app into a Java jar file
|
|
64
64
|
test_files: []
|