jarbler 0.4.0 → 0.4.2
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 +3 -2
- data/lib/jarbler/JarMain.java +87 -1
- data/lib/jarbler/builder.rb +20 -4
- data/lib/jarbler/config.rb +19 -11
- data/lib/jarbler/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af40fd597f65765920d0825c739db3604cd8ec0d6a975889e10b9f17b0869dce
|
4
|
+
data.tar.gz: 3b887f4cb0ce06669a78da49cdc3f28fd7137cca0e7cd7eeebd60cfc1f8a3f2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b07fc51c641293913293b3d3cf4713e306f73c3f746237406905dfe973f31ca08497db7a35ebb1d870bc89a2690aa5775fbfe84c1bd120108cc3c7bb4e8fe786
|
7
|
+
data.tar.gz: 6b8ef9fe88116c68b47ad5fc7d3f7923d8a8e0d5c5b511fbe1c9a9a179841ab95035fa65dd3761f7d1466e2d0df9176b8061eed9dc548109290499cb07f04783
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.4.2] - 2025-07-24
|
4
|
+
|
5
|
+
- Native Gem extensions are also copied into the jar file if the Gem has a native extension<br/>
|
6
|
+
If the extension is of platform type 'universal-java-XX' then the 'XX' in the dir name 'universal-java-XX' is corrected with the real Java major version at start of the jar file.<br/>
|
7
|
+
Extensions of other platform types are copied as is.
|
8
|
+
|
9
|
+
## [0.4.1] - 2025-07-15
|
10
|
+
|
11
|
+
- config attribute 'gemfile_groups' established to specify the groups of the Gemfile which should be included in the jar file
|
3
12
|
|
4
13
|
## [0.4.0] - 2025-04-24
|
5
14
|
|
data/README.md
CHANGED
@@ -56,10 +56,11 @@ The default configuration is focused on Ruby on Rails applications.<br>
|
|
56
56
|
| Option | Default value | Description |
|
57
57
|
|-----------------------|------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
58
58
|
| compile_ruby_files | false | Ahead of time compilation of all .rb files of the application to .class files.<br/>Only the .class files are stored in the jar file. The Gem dependencies are not compiled. Requires JRuby as Ruby environment at compile time. |
|
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
59
|
| excludes_from_compile | [] | The files and dirs of the project to exclude from the compilation of .rb files. Paths specifies the location in the jar file (e.g. ["app_root/file.rb"] ) |
|
62
60
|
| excludes | ["tmp/cache", "tmp/pids", ...] (see generated template file for whole content) | The files and dirs of the project to exclude from the include option |
|
61
|
+
| 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. |
|
62
|
+
| executable_params | ["server", "-e", "production", "-p", "8080"] | Command line parameters to be used for the ruby executable |
|
63
|
+
| gemfile_groups | [:default, :production] | List of groups from Gemfile to include in the jar file, e.g. [:default, :production, :development, :test].<br/>Group :default are all gems not assigned to a specific group. |
|
63
64
|
| 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
65
|
| jar_name | < Name of project dir >.jar | The name of the generated jar file |
|
65
66
|
| java_opts | none | Additional options for the Java compiler (javac).<br/>Used for the compilation of the jar file bootstrap class JarMain.java.<br/>Does not influence the optional AOT compilation of the application's ruby files.<br/>E.g. control the class file version of the JarMain.class with `java_opts = '-target 1.8 -source 1.8‘`. |
|
data/lib/jarbler/JarMain.java
CHANGED
@@ -157,6 +157,11 @@ class JarMain {
|
|
157
157
|
//debug("JRuby set property 'jruby.gem.home' to '" + full_gem_home + "'");
|
158
158
|
//System.setProperty("jruby.gem.home", full_gem_home);
|
159
159
|
|
160
|
+
// Enable JRuby warnings, not proof to really function
|
161
|
+
System.setProperty("jruby.log.warnings", "true");
|
162
|
+
System.setProperty("jruby.cli.verbose", "true");
|
163
|
+
// System.setProperty("jruby.debug.fullTrace", "true");
|
164
|
+
|
160
165
|
debug("JRuby program starts with the following arguments: ");
|
161
166
|
for (String arg : mainArgs) {
|
162
167
|
debug(" - " + arg);
|
@@ -244,7 +249,16 @@ class JarMain {
|
|
244
249
|
*/
|
245
250
|
private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
|
246
251
|
try {
|
247
|
-
|
252
|
+
String destFileName = zipEntry.getName();
|
253
|
+
|
254
|
+
// the platform name in extension dir depends on the the target java version, therfore we replace the platform name here
|
255
|
+
if (destFileName.contains("universal-java-XX")) {
|
256
|
+
String newPlatformName = "universal-java-" + javaMajorRelease4RubyPlatform();
|
257
|
+
debug ("Replacing platform name in file '" + destFileName + "' from 'universal-java-XX' to '" + newPlatformName + "'");
|
258
|
+
destFileName = destFileName.replace("universal-java-XX", newPlatformName);
|
259
|
+
}
|
260
|
+
|
261
|
+
File destFile = new File(destinationDir, destFileName);
|
248
262
|
|
249
263
|
String destDirPath = destinationDir.getCanonicalPath();
|
250
264
|
String destFilePath = destFile.getCanonicalPath();
|
@@ -348,4 +362,76 @@ class JarMain {
|
|
348
362
|
System.err.println(errorSummary);
|
349
363
|
}
|
350
364
|
}
|
365
|
+
|
366
|
+
/**
|
367
|
+
* Get the major release of the Java platform a'la universal-java-XX
|
368
|
+
* @return [int] The major release of the Java platform, e.g. "java-universal-11"
|
369
|
+
*/
|
370
|
+
|
371
|
+
private static int javaMajorRelease4RubyPlatform() {
|
372
|
+
try {
|
373
|
+
// --- Ansatz 1: Für Java 9 und höher (empfohlen) ---
|
374
|
+
// Versuche, Runtime.version() zu verwenden.
|
375
|
+
// Wir nutzen Reflection, damit der Code auch mit einem Java 8 JDK kompiliert werden kann,
|
376
|
+
// aber trotzdem die moderne API verwendet, wenn er auf einem Java 9+ JRE läuft.
|
377
|
+
Class<?> runtimeClass = Class.forName("java.lang.Runtime");
|
378
|
+
Method versionMethod = runtimeClass.getMethod("version");
|
379
|
+
Object versionObject = versionMethod.invoke(null); // Runtime.version() ist eine statische Methode
|
380
|
+
|
381
|
+
// Hole die "major" Methode vom zurückgegebenen Runtime.Version Objekt
|
382
|
+
Class<?> versionClass = Class.forName("java.lang.Runtime$Version");
|
383
|
+
Method majorMethod = versionClass.getMethod("major");
|
384
|
+
return (int) majorMethod.invoke(versionObject);
|
385
|
+
|
386
|
+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | java.lang.reflect.InvocationTargetException e) {
|
387
|
+
// --- Ansatz 2: Fallback für Java 8 und älter ---
|
388
|
+
// Dieser Block wird ausgeführt, wenn Runtime.version() nicht verfügbar ist
|
389
|
+
// (z.B. auf Java 8) oder wenn Reflection fehlschlägt.
|
390
|
+
|
391
|
+
String javaVersion = System.getProperty("java.version");
|
392
|
+
// Beispiele für java.version:
|
393
|
+
// Java 8: "1.8.0_291"
|
394
|
+
// Java 11: "11.0.11"
|
395
|
+
// Java 17: "17.0.2"
|
396
|
+
// Java 9: "9" (manchmal ohne weitere Punkte)
|
397
|
+
|
398
|
+
// Prüfe, ob es sich um das alte "1.x.y" Format handelt
|
399
|
+
if (javaVersion.startsWith("1.")) {
|
400
|
+
// Für "1.x.y_z" ist die Hauptversion 'x'
|
401
|
+
// Beispiel: "1.8.0_291" -> '8'
|
402
|
+
try {
|
403
|
+
return Integer.parseInt(javaVersion.substring(2, 3));
|
404
|
+
} catch (NumberFormatException ex) {
|
405
|
+
// Sollte nicht passieren, aber zur Sicherheit
|
406
|
+
System.err.println("Fehler beim Parsen der Java 1.x Version: " + javaVersion + " - " + ex.getMessage());
|
407
|
+
return -1;
|
408
|
+
}
|
409
|
+
} else {
|
410
|
+
// Für "x.y.z" oder "x" Format (Java 9+ Stil)
|
411
|
+
// Beispiel: "11.0.11" -> '11', "17.0.2" -> '17', "9" -> '9'
|
412
|
+
int dotIndex = javaVersion.indexOf('.');
|
413
|
+
if (dotIndex != -1) {
|
414
|
+
try {
|
415
|
+
return Integer.parseInt(javaVersion.substring(0, dotIndex));
|
416
|
+
} catch (NumberFormatException ex) {
|
417
|
+
System.err.println("Fehler beim Parsen der Java x.y Version: " + javaVersion + " - " + ex.getMessage());
|
418
|
+
return -1;
|
419
|
+
}
|
420
|
+
} else {
|
421
|
+
// Fallback für den Fall, dass nur die Hauptversion angegeben ist (z.B. "9", "10", "11")
|
422
|
+
try {
|
423
|
+
return Integer.parseInt(javaVersion);
|
424
|
+
} catch (NumberFormatException ex) {
|
425
|
+
System.err.println("Fehler beim Parsen der Java Hauptversion: " + javaVersion + " - " + ex.getMessage());
|
426
|
+
return -1;
|
427
|
+
}
|
428
|
+
}
|
429
|
+
}
|
430
|
+
} catch (NumberFormatException e) {
|
431
|
+
// Dieser Catch-Block fängt Fehler ab, die auftreten, wenn System.getProperty("java.version")
|
432
|
+
// ein unerwartetes Format hat, das nicht geparst werden kann.
|
433
|
+
System.err.println("Fehler beim Parsen der Java-Versionszeichenkette: " + System.getProperty("java.version") + " - " + e.getMessage());
|
434
|
+
return -1;
|
435
|
+
}
|
436
|
+
}
|
351
437
|
}
|
data/lib/jarbler/builder.rb
CHANGED
@@ -10,7 +10,7 @@ module Jarbler
|
|
10
10
|
class Builder
|
11
11
|
# Execute all functions needed to build the jar file
|
12
12
|
# Should be executed in application directory of Rails/Ruby application
|
13
|
-
# @return [
|
13
|
+
# @return [String] Ruby minor version of the JRuby jars with patch level set to 0
|
14
14
|
def build_jar
|
15
15
|
debug "Running with Ruby version '#{RUBY_VERSION}' on platform '#{RUBY_PLATFORM}'. Engine '#{RUBY_ENGINE}' version '#{RUBY_ENGINE_VERSION}'"
|
16
16
|
|
@@ -72,6 +72,7 @@ module Jarbler
|
|
72
72
|
# place the jar in project directory
|
73
73
|
file_utils_copy(config.jar_name, app_root)
|
74
74
|
puts "Created jar file #{app_root}/#{config.jar_name}"
|
75
|
+
ruby_minor_version # Used in tests to know the target Gem dir
|
75
76
|
end
|
76
77
|
rescue Exception => e
|
77
78
|
puts "Error: #{e.message}"
|
@@ -94,11 +95,15 @@ module Jarbler
|
|
94
95
|
# @return [void]
|
95
96
|
def copy_needed_gems_to_staging(staging_dir, ruby_minor_version)
|
96
97
|
gem_target_location = "#{staging_dir}/gems/jruby/#{ruby_minor_version}"
|
98
|
+
|
99
|
+
# Replace universal-java-XX with the correct platform for the current Java version after unzipping of the jar file
|
100
|
+
extension_target_location = "#{gem_target_location}/extensions/universal-java-XX/#{ruby_minor_version}"
|
101
|
+
|
97
102
|
FileUtils.mkdir_p("#{gem_target_location}/bin")
|
98
103
|
FileUtils.mkdir_p("#{gem_target_location}/build_info")
|
99
104
|
FileUtils.mkdir_p("#{gem_target_location}/cache")
|
100
105
|
FileUtils.mkdir_p("#{gem_target_location}/doc")
|
101
|
-
FileUtils.mkdir_p(
|
106
|
+
FileUtils.mkdir_p(extension_target_location)
|
102
107
|
FileUtils.mkdir_p("#{gem_target_location}/gems")
|
103
108
|
FileUtils.mkdir_p("#{gem_target_location}/specifications")
|
104
109
|
FileUtils.mkdir_p("#{gem_target_location}/bundler/bin")
|
@@ -114,8 +119,10 @@ module Jarbler
|
|
114
119
|
# differentiate between Gems from git/bundler and Gems from rubygems
|
115
120
|
if spec.source.is_a?(Bundler::Source::Git)
|
116
121
|
# Copy the Gem from bundler/gems including the gemspec
|
122
|
+
debug "Adding Bundler Gem from dir '#{spec.gem_dir}' into jar file at temporary location '#{gem_target_location}/gems'"
|
117
123
|
file_utils_copy(spec.gem_dir, "#{gem_target_location}/bundler/gems")
|
118
124
|
spec.executables.each do |executable|
|
125
|
+
debug "Adding executable of Bundler Gem from dir '#{spec.bin_dir}#{executable}/' into jar file at temporary location '#{gem_target_location}/bundler/bin'"
|
119
126
|
file_utils_copy("#{spec.bin_dir}/#{executable}", "#{gem_target_location}/bundler/bin")
|
120
127
|
end
|
121
128
|
else # Gem is from rubygems
|
@@ -123,10 +130,19 @@ module Jarbler
|
|
123
130
|
# Should the default gems are also copied to the staging directory?
|
124
131
|
unless spec.default_gem? # Do not copy default gems, because they are already included in the jruby jars standard library
|
125
132
|
# copy the Gem and gemspec separately
|
133
|
+
debug "Adding local Gem from dir '#{spec.gem_dir}' into jar file at temporary location '#{gem_target_location}/gems'"
|
126
134
|
file_utils_copy(spec.gem_dir, "#{gem_target_location}/gems")
|
135
|
+
|
136
|
+
if spec.extension_dir && Dir.exist?(spec.extension_dir)
|
137
|
+
debug "Adding extension from dir '#{spec.extension_dir}' into jar file at temporary location '#{extension_target_location}'"
|
138
|
+
puts "Adding extension from dir '#{spec.extension_dir}' into jar file but extension is not for platform 'universal-java-xx'!!!" unless spec.extension_dir['universal-java']
|
139
|
+
file_utils_copy(spec.extension_dir, extension_target_location)
|
140
|
+
end
|
141
|
+
|
127
142
|
# spec.loaded_from contains the path to the gemspec file including the path prefix "default/" for default gems
|
128
143
|
file_utils_copy(spec.loaded_from, "#{gem_target_location}/specifications")
|
129
144
|
spec.executables.each do |executable|
|
145
|
+
debug "Adding executable of local Gem from dir '#{spec.bin_dir}#{executable}/' into jar file at temporary location '#{gem_target_location}/bin'"
|
130
146
|
file_utils_copy("#{spec.bin_dir}/#{executable}", "#{gem_target_location}/bin")
|
131
147
|
end
|
132
148
|
end
|
@@ -144,10 +160,10 @@ module Jarbler
|
|
144
160
|
lockfile_parser = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile))
|
145
161
|
lockfile_specs = lockfile_parser.specs
|
146
162
|
|
147
|
-
Bundler.setup # Load Gems specified in Gemfile, ensure that Gem path also includes the Gems loaded into bundler dir
|
163
|
+
Bundler.setup(*config.gemfile_groups) # Load Gems specified in Gemfile, ensure that Gem path also includes the Gems loaded into bundler dir
|
148
164
|
# filter Gems needed for production
|
149
165
|
gemfile_specs = Bundler.definition.dependencies.select do |d|
|
150
|
-
d.groups.
|
166
|
+
!(d.groups & config.gemfile_groups).empty? # Check if the Gem is in the groups specified in config.gemfile_groups
|
151
167
|
end
|
152
168
|
|
153
169
|
debug "Gems from Gemfile needed for production:"
|
data/lib/jarbler/config.rb
CHANGED
@@ -9,6 +9,7 @@ module Jarbler
|
|
9
9
|
:excludes_from_compile,
|
10
10
|
:executable,
|
11
11
|
:executable_params,
|
12
|
+
:gemfile_groups,
|
12
13
|
:includes,
|
13
14
|
:java_opts,
|
14
15
|
:jar_name,
|
@@ -47,6 +48,7 @@ module Jarbler
|
|
47
48
|
puts " excludes_from_compile: #{config.excludes_from_compile}" if config.compile_ruby_files
|
48
49
|
puts " executable: #{config.executable}"
|
49
50
|
puts " executable_params: #{config.executable_params}"
|
51
|
+
puts " gemfile_groups: #{config.gemfile_groups}"
|
50
52
|
puts " includes: #{config.includes}"
|
51
53
|
puts " jar_name: #{config.jar_name}"
|
52
54
|
puts " java_opts: #{config.java_opts}"
|
@@ -57,17 +59,18 @@ module Jarbler
|
|
57
59
|
end
|
58
60
|
|
59
61
|
def initialize
|
60
|
-
@compile_ruby_files
|
61
|
-
@compile_java_version
|
62
|
-
@excludes
|
63
|
-
@excludes_from_compile
|
64
|
-
@executable
|
65
|
-
@executable_params
|
66
|
-
@
|
67
|
-
@
|
68
|
-
@
|
69
|
-
@
|
70
|
-
@
|
62
|
+
@compile_ruby_files = false
|
63
|
+
@compile_java_version = nil # deprecated, use java_opts instead
|
64
|
+
@excludes = %w(tmp/cache tmp/pids tmp/sockets vendor/bundle vendor/cache vendor/ruby)
|
65
|
+
@excludes_from_compile = []
|
66
|
+
@executable = 'bin/rails'
|
67
|
+
@executable_params = %w(server -e production -p 8080)
|
68
|
+
@gemfile_groups = [:default, :production]
|
69
|
+
@includes = %w(app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile script vendor tmp)
|
70
|
+
@java_opts = nil
|
71
|
+
@jar_name = File.basename(Dir.pwd) + '.jar'
|
72
|
+
@jrubyc_opts = []
|
73
|
+
@jruby_version = nil # determined automatically at runtime
|
71
74
|
# execute additional block if given
|
72
75
|
yield self if block_given?
|
73
76
|
end
|
@@ -93,6 +96,10 @@ module Jarbler
|
|
93
96
|
# Additional command line parameters for the Ruby executable
|
94
97
|
# config.executable_params = #{executable_params}
|
95
98
|
|
99
|
+
# List of groups from Gemfile to include in the jar file, e.g. [:default, :production, :development, :test]
|
100
|
+
# group :default are all gems not assigned to a specific group
|
101
|
+
# config.gemfile_groups = #{gemfile_groups}
|
102
|
+
|
96
103
|
# Application directories or files to include in the jar file
|
97
104
|
# config.includes = #{includes}
|
98
105
|
# config.includes << 'additional'
|
@@ -187,6 +194,7 @@ module Jarbler
|
|
187
194
|
raise "Invalid config value for jar name: #{jar_name}" unless jar_name =~ /\w+/
|
188
195
|
raise "Invalid config value for executable: #{executable}" unless executable =~ /\w+/
|
189
196
|
raise "Invalid config value for executable params: #{executable_params}" unless executable_params.is_a?(Array)
|
197
|
+
raise "Invalid config value for gemfile groups: #{gemfile_groups}" unless gemfile_groups.is_a?(Array)
|
190
198
|
raise "Invalid config value for includes: #{includes}" unless includes.is_a?(Array)
|
191
199
|
raise "Invalid config value for excludes: #{excludes}" unless excludes.is_a?(Array)
|
192
200
|
raise "Invalid config value for compile_ruby_files: #{compile_ruby_files}" unless [true, false].include?(compile_ruby_files)
|
data/lib/jarbler/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jarbler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ramm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
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'
|