ocran 1.4.2-x86_64-linux → 1.4.3-x86_64-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8ae157a9de1441f400873047957620d2c6f41c47371ba0e0a1c4a00be2399fe
4
- data.tar.gz: 21dc8dc3b6ef0c91af1d96547c4701b0c16e347e386304cd756f6fd6aeda8985
3
+ metadata.gz: 395439e25a66520b23294233b659afd5cb48a057c37919881652eabc2fc3e00d
4
+ data.tar.gz: 0b5d425c967a32fce5c82ebe1e61e1c73925b59c794ef00df3bc2553d3ac43bf
5
5
  SHA512:
6
- metadata.gz: 4063ae4a93a90dc0f1dd9ee4d96cdddceb3a4c28836830e06e4827386fbd79f9ec646b1007d542c7e1653396541356636fdaeaccef42231835ebd5b59f464dfa
7
- data.tar.gz: '00696824bb66b0144751b042bb152eee43c51e929ae05c4e4bae8e706c698cd945db0be3eba37708ca7290e0b8cca3a053883452242c8520c84ed45d5ce7a7eb'
6
+ metadata.gz: b5d09a2b2e5bcb3af38e1b9978335722518a1638003d1cd2f361426496650fc40214ca4885be04d35f9d494274baef87316ef9ee56078b4d550341925162eb4c
7
+ data.tar.gz: e68646927cf875767dab3eb4c1ce7a376c07d77a89f8f97fc13f34da3d4fb33400e8faa9e08a1828603a8ca24f673121bac46f070fdc7ec7f938662b2148a0d7
data/CHANGELOG.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 1.4.3
2
+ - Migrate edicon from C to Ruby: replace edicon.exe with a pure-Ruby implementation (ed_icon.rb), fixing incorrect BeginUpdateResource error checking and wrong GroupIconSize calculation. Shortens build times and removes the C binary from the build.
3
+ - Include Gem.default_dir in GEM_PATH on all platforms: previously the exec_prefix gem directory was excluded on Windows, causing native-extension gems (e.g. fxruby/fox16) to fail at runtime with a LoadError even though they were bundled correctly.
4
+ - Add FXRuby (fox16) test: verify that native extension DLLs are bundled correctly so the packaged executable does not raise a LoadError at runtime.
5
+ - CI: start a virtual display (xpra + Xorg dummy driver with GLX) on Linux before running tests so FXRuby's X11 requirement is satisfied.
6
+ - CI: install XQuartz on macOS runners and add it to the portability test job so FXRuby can connect to a display on both test and portability jobs.
7
+
1
8
  === 1.4.2
2
9
  - Auto-bundle OpenSSL and all its transitive dependencies (openssl.rb, digest.so, etc.) when net/http is loaded but no HTTPS request was made during the dependency scan. OpenSSL is now required inside the OCRAN build process so every file it pulls in appears in the bundled executable.
3
10
  - Add companion DLL scan on windows: when a native extension (.so) within the Ruby installation is loaded, all DLLs in the same directory are proactively included. This ensures libssl-3-x64.dll, libcrypto-3-x64.dll, libwinpthread-1.dll, and libyaml-0-2.dll are bundled even when no HTTPS connection is made during the build scan.
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # ocran
2
2
 
3
3
  home :: https://github.com/largo/ocran/
4
-
5
4
  issues :: http://github.com/largo/ocran/issues
6
5
 
7
6
  ## Description
@@ -23,18 +22,19 @@ Ruby 3.2+ compatibility.
23
22
 
24
23
  ## Recommended usage
25
24
 
26
- The most common use-case is shipping a program to Windows servers or users
27
- who do not have Ruby installed. By default, each time the `.exe` is opened it
25
+ The most common use-case is shipping a program to users running Windows / Linux / macOS
26
+ who do not have Ruby installed. By default, each time the `.exe` / executable is opened it
28
27
  extracts the Ruby interpreter and your code to a temporary directory and runs
29
28
  them from there.
30
29
 
31
- Because extraction takes time on each launch, consider using the Inno Setup
30
+ Because extraction takes time on each launch, use `--output-dir` or
31
+ `--output-zip` to produce a portable directory/archive that runs with the
32
+ bundled Ruby on Linux, macOS, or Windows.
33
+ If using Windows you can use the Inno Setup
32
34
  option (`--innosetup`) to produce a proper installer that extracts once to a
33
35
  permanent directory.
34
36
 
35
- For cross-platform packaging or CI artifacts, use `--output-dir` or
36
- `--output-zip` to produce a portable directory/archive that runs with the
37
- bundled Ruby on Linux, macOS, or Windows.
37
+ You can easily generate binaries for the supported Operating Systems with GitHub Actions.
38
38
 
39
39
  ## Features
40
40
 
@@ -74,12 +74,12 @@ https://github.com/largo/ocran/releases/.
74
74
 
75
75
  ## Synopsis
76
76
 
77
- ### Building a Windows executable:
77
+ ### Building an executable:
78
78
 
79
79
  ocran script.rb
80
80
 
81
81
  Packages `script.rb`, the Ruby interpreter, and all dependencies (gems and
82
- DLLs) into `script.exe`.
82
+ DLLs) into `script.exe` or `script` on Linux or macOS.
83
83
 
84
84
  ### Building a portable directory (Linux / macOS / Windows):
85
85
 
@@ -243,7 +243,8 @@ a Linux runner for Linux builds).
243
243
  ## Requirements
244
244
 
245
245
  * Ruby 3.2+
246
- * For building Windows `.exe`: Windows with RubyInstaller DevKit (mingw-w64), or Wine on Linux/macOS
246
+ * For building Windows `.exe`: Windows with [RubyInstaller DevKit](https://rubyinstaller.org/downloads/) (mingw-w64), or Wine on Linux/macOS
247
+ * For building Linux and MacOS binaries: the respective build tools
247
248
  * For `--output-dir` / `--output-zip`: any platform with Ruby 3.2+
248
249
  * For `--output-zip` on Linux/macOS: the `zip` command must be available
249
250
  * For `--output-zip` on Windows: PowerShell (included in Windows 8+)
@@ -526,6 +527,11 @@ file:
526
527
  end
527
528
  end
528
529
 
530
+ ## See elsewhere
531
+
532
+ - [State of Ruby Packagers](https://gist.github.com/YOU54F/3775e66e6090e0371c11601e6b75c305)
533
+ - [Traveling Ruby](https://github.com/trubygems/traveling-ruby)
534
+
529
535
  ## Credits
530
536
 
531
537
  Lars Christensen and contributors for the OCRA project which this is forked from.
@@ -514,14 +514,15 @@ module Ocran
514
514
  builder.set_env_path("GEM_HOME", GEMDIR)
515
515
 
516
516
  gem_paths = [GEMDIR]
517
- # On POSIX, default gems (e.g. error_highlight) are stored under the Ruby
518
- # installation's gem dir (Gem.default_dir), not in GEMDIR. Include it in
519
- # GEM_PATH so RubyGems can find and activate them in the extracted tree.
520
- unless Gem.win_platform?
521
- default_gem_dir = Pathname(Gem.default_dir)
522
- if default_gem_dir.subpath?(exec_prefix)
523
- gem_paths << default_gem_dir.relative_path_from(exec_prefix)
524
- end
517
+ # Gems installed under the Ruby prefix (exec_prefix) have their specs and
518
+ # extension dirs placed there via duplicate_to_exec_prefix. Include
519
+ # Gem.default_dir (relative to exec_prefix) in GEM_PATH so RubyGems can
520
+ # find and activate them at runtime. This is required on both Windows
521
+ # (e.g. fxruby/fox16 whose fox16_c.so lives in extension_dir under the
522
+ # Ruby prefix) and POSIX (e.g. error_highlight default gems).
523
+ default_gem_dir = Pathname(Gem.default_dir)
524
+ if default_gem_dir.subpath?(exec_prefix)
525
+ gem_paths << default_gem_dir.relative_path_from(exec_prefix)
525
526
  end
526
527
  builder.set_env_path("GEM_PATH", *gem_paths)
527
528
 
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+ require "fiddle/import"
3
+ require "fiddle/types"
4
+
5
+ module Ocran
6
+ # Changes the Icon in a PE executable.
7
+ module EdIcon
8
+ extend Fiddle::Importer
9
+ dlload "kernel32.dll"
10
+
11
+ include Fiddle::Win32Types
12
+ typealias "LPVOID", "void*"
13
+ typealias "LPCWSTR", "char*"
14
+
15
+ module Successive
16
+ include Enumerable
17
+
18
+ def each
19
+ return to_enum(__method__) unless block_given?
20
+
21
+ entry = self
22
+ while true
23
+ yield(entry)
24
+ entry = self.class.new(tail)
25
+ end
26
+ end
27
+
28
+ def tail
29
+ to_ptr + self.class.size
30
+ end
31
+ end
32
+
33
+ # Icon file header
34
+ IconHeader = struct(
35
+ [
36
+ "WORD Reserved",
37
+ "WORD ResourceType",
38
+ "WORD ImageCount"
39
+ ]
40
+ ).include(Successive)
41
+
42
+ icon_info = [
43
+ "BYTE Width",
44
+ "BYTE Height",
45
+ "BYTE Colors",
46
+ "BYTE Reserved",
47
+ "WORD Planes",
48
+ "WORD BitsPerPixel",
49
+ "DWORD ImageSize"
50
+ ]
51
+
52
+ # Icon File directory entry structure
53
+ IconDirectoryEntry = struct(icon_info + ["DWORD ImageOffset"]).include(Successive)
54
+
55
+ # Group Icon Resource directory entry structure
56
+ IconDirResEntry = struct(icon_info + ["WORD ResourceID"]).include(Successive)
57
+
58
+ class IconFile < IconHeader
59
+ def initialize(icon_filename)
60
+ @data = File.binread(icon_filename)
61
+ super(Fiddle::Pointer.to_ptr(@data))
62
+
63
+ entries_end = IconHeader.size + self.ImageCount * IconDirectoryEntry.size
64
+ if entries_end > @data.bytesize
65
+ raise "Icon file too small for declared ImageCount"
66
+ end
67
+
68
+ entries.each_with_index do |entry, i|
69
+ if entry.ImageOffset + entry.ImageSize > @data.bytesize
70
+ raise "Icon entry #{i} exceeds file bounds"
71
+ end
72
+ end
73
+ end
74
+
75
+ def entries
76
+ IconDirectoryEntry.new(self.tail).take(self.ImageCount)
77
+ end
78
+ end
79
+
80
+ class GroupIcon < IconHeader
81
+ attr_reader :size
82
+
83
+ def initialize(image_count, resource_type)
84
+ @size = IconHeader.size + image_count * IconDirResEntry.size
85
+ super(Fiddle.malloc(@size), Fiddle::RUBY_FREE)
86
+ self.Reserved = 0
87
+ self.ResourceType = resource_type
88
+ self.ImageCount = image_count
89
+ end
90
+
91
+ def entries
92
+ IconDirResEntry.new(self.tail).take(self.ImageCount)
93
+ end
94
+ end
95
+
96
+ MAKEINTRESOURCE = -> (i) { Fiddle::Pointer.new(i) }
97
+ RT_ICON = MAKEINTRESOURCE.(3)
98
+ RT_GROUP_ICON = MAKEINTRESOURCE.(RT_ICON.to_i + 11)
99
+
100
+ MAKELANGID = -> (p, s) { s << 10 | p }
101
+ LANG_NEUTRAL = 0x00
102
+ SUBLANG_DEFAULT = 0x01
103
+ LANGID = MAKELANGID.(LANG_NEUTRAL, SUBLANG_DEFAULT)
104
+
105
+ extern "DWORD GetLastError()"
106
+ extern "HANDLE BeginUpdateResourceW(LPCWSTR, BOOL)"
107
+ extern "BOOL EndUpdateResourceW(HANDLE, BOOL)"
108
+ extern "BOOL UpdateResourceW(HANDLE, LPCWSTR, LPCWSTR, WORD, LPVOID, DWORD)"
109
+
110
+ class << self
111
+ def update_icon(executable_filename, icon_filename)
112
+ update_resource(executable_filename) do |handle|
113
+ icon_file = IconFile.new(icon_filename)
114
+ icon_entries = icon_file.entries
115
+
116
+ # Create the RT_ICON resources
117
+ icon_entries.each_with_index do |entry, i|
118
+ if UpdateResourceW(handle, RT_ICON, 101 + i, LANGID, icon_file.to_i + entry.ImageOffset, entry.ImageSize) == 0
119
+ raise "failed to UpdateResource(#{GetLastError()})"
120
+ end
121
+ end
122
+
123
+ # Create the RT_GROUP_ICON structure
124
+ group_icon = GroupIcon.new(icon_file.ImageCount, icon_file.ResourceType)
125
+ group_icon.entries.zip(icon_entries).each_with_index do |(res, icon), i|
126
+ res.Width = icon.Width
127
+ res.Height = icon.Height
128
+ res.Colors = icon.Colors
129
+ res.Reserved = icon.Reserved
130
+ res.Planes = icon.Planes
131
+ res.BitsPerPixel = icon.BitsPerPixel
132
+ res.ImageSize = icon.ImageSize
133
+ res.ResourceID = 101 + i
134
+ end
135
+
136
+ # Save the RT_GROUP_ICON resource
137
+ if UpdateResourceW(handle, RT_GROUP_ICON, 100, LANGID, group_icon, group_icon.size) == 0
138
+ raise "Failed to create group icon(#{GetLastError()})"
139
+ end
140
+ end
141
+ end
142
+
143
+ def update_resource(executable_filename)
144
+ handle = BeginUpdateResourceW(executable_filename.encode("UTF-16LE"), 0)
145
+ if handle == Fiddle::NULL
146
+ raise "Failed to BeginUpdateResourceW(#{GetLastError()})"
147
+ end
148
+
149
+ yield(handle)
150
+
151
+ if EndUpdateResourceW(handle, 0) == 0
152
+ raise "Failed to EndUpdateResourceW(#{GetLastError()})"
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -27,7 +27,6 @@ module Ocran
27
27
  STUB_PATH = File.expand_path(WINDOWS ? "stub.exe" : "stub", base_dir)
28
28
  STUBW_PATH = WINDOWS ? File.expand_path("stubw.exe", base_dir) : nil
29
29
  LZMA_PATH = WINDOWS ? File.expand_path("lzma.exe", base_dir) : nil
30
- EDICON_PATH = WINDOWS ? File.expand_path("edicon.exe", base_dir) : nil
31
30
 
32
31
  def self.find_posix_lzma_cmd
33
32
  if system("which lzma > /dev/null 2>&1")
@@ -122,7 +121,8 @@ module Ocran
122
121
 
123
122
  # Embed icon resource (Windows only)
124
123
  if icon_path && WINDOWS
125
- system(EDICON_PATH, stub, icon_path.to_s, exception: true)
124
+ require_relative "ed_icon"
125
+ EdIcon.update_icon(stub, icon_path.to_s)
126
126
  end
127
127
 
128
128
  File.open(stub, "ab") do |of|
data/lib/ocran/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ocran
4
- VERSION = "1.4.2"
4
+ VERSION = "1.4.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ocran
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Andi Idogawa
@@ -64,6 +64,7 @@ files:
64
64
  - lib/ocran/command_output.rb
65
65
  - lib/ocran/dir_builder.rb
66
66
  - lib/ocran/direction.rb
67
+ - lib/ocran/ed_icon.rb
67
68
  - lib/ocran/empty_source
68
69
  - lib/ocran/file_path_set.rb
69
70
  - lib/ocran/gem_spec_queryable.rb
@@ -102,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
103
  - !ruby/object:Gem::Version
103
104
  version: '0'
104
105
  requirements: []
105
- rubygems_version: 4.0.3
106
+ rubygems_version: 4.0.6
106
107
  specification_version: 4
107
108
  summary: OCRAN (One-Click Ruby Application Next) packages Ruby applications for distribution
108
109
  on Windows, Linux, and macOS.