kompo 0.2.0 → 0.3.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.
@@ -0,0 +1,365 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+ module Kompo
5
+ # Section to handle platform-specific dependencies.
6
+ # Switches implementation based on the current platform.
7
+ # Exports lib_paths for linker flags (e.g., "-L/usr/local/lib")
8
+ class InstallDeps < Taski::Section
9
+ interfaces :lib_paths
10
+
11
+ def impl
12
+ macos? ? ForMacOS : ForLinux
13
+ end
14
+
15
+ # macOS implementation - installs dependencies via Homebrew
16
+ class ForMacOS < Taski::Task
17
+ def run
18
+ # HomebrewPath.path triggers Homebrew installation if not present
19
+ @lib_paths = [
20
+ InstallGmp.lib_path,
21
+ InstallOpenssl.lib_path,
22
+ InstallReadline.lib_path,
23
+ InstallLibyaml.lib_path,
24
+ InstallZlib.lib_path,
25
+ InstallLibffi.lib_path
26
+ ].compact.join(' ')
27
+
28
+ puts 'All Homebrew dependencies installed'
29
+ end
30
+
31
+ # GMP library installation Section
32
+ class InstallGmp < Taski::Section
33
+ interfaces :lib_path
34
+
35
+ def impl
36
+ brew = HomebrewPath.path
37
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
38
+ end
39
+
40
+ BREW_NAME = 'gmp'
41
+ MARKER_FILE = File.expand_path('~/.kompo_installed_gmp')
42
+
43
+ class Installed < Taski::Task
44
+ def run
45
+ brew = HomebrewPath.path
46
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
47
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
48
+ puts "#{BREW_NAME} is already installed"
49
+ end
50
+ end
51
+
52
+ class Install < Taski::Task
53
+ def run
54
+ brew = HomebrewPath.path
55
+ puts "Installing #{BREW_NAME}..."
56
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
57
+ File.write(MARKER_FILE, 'installed')
58
+
59
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
60
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
61
+ end
62
+
63
+ def clean
64
+ return unless File.exist?(MARKER_FILE)
65
+
66
+ brew = HomebrewPath.path
67
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
68
+ system("#{brew} uninstall #{BREW_NAME}")
69
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
70
+ end
71
+ end
72
+ end
73
+
74
+ # OpenSSL library installation Section
75
+ class InstallOpenssl < Taski::Section
76
+ interfaces :lib_path
77
+
78
+ def impl
79
+ brew = HomebrewPath.path
80
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
81
+ end
82
+
83
+ BREW_NAME = 'openssl@3'
84
+ MARKER_FILE = File.expand_path('~/.kompo_installed_openssl')
85
+
86
+ class Installed < Taski::Task
87
+ def run
88
+ brew = HomebrewPath.path
89
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
90
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
91
+ puts "#{BREW_NAME} is already installed"
92
+ end
93
+ end
94
+
95
+ class Install < Taski::Task
96
+ def run
97
+ brew = HomebrewPath.path
98
+ puts "Installing #{BREW_NAME}..."
99
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
100
+ File.write(MARKER_FILE, 'installed')
101
+
102
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
103
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
104
+ end
105
+
106
+ def clean
107
+ return unless File.exist?(MARKER_FILE)
108
+
109
+ brew = HomebrewPath.path
110
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
111
+ system("#{brew} uninstall #{BREW_NAME}")
112
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
113
+ end
114
+ end
115
+ end
116
+
117
+ # Readline library installation Section
118
+ class InstallReadline < Taski::Section
119
+ interfaces :lib_path
120
+
121
+ def impl
122
+ brew = HomebrewPath.path
123
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
124
+ end
125
+
126
+ BREW_NAME = 'readline'
127
+ MARKER_FILE = File.expand_path('~/.kompo_installed_readline')
128
+
129
+ class Installed < Taski::Task
130
+ def run
131
+ brew = HomebrewPath.path
132
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
133
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
134
+ puts "#{BREW_NAME} is already installed"
135
+ end
136
+ end
137
+
138
+ class Install < Taski::Task
139
+ def run
140
+ brew = HomebrewPath.path
141
+ puts "Installing #{BREW_NAME}..."
142
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
143
+ File.write(MARKER_FILE, 'installed')
144
+
145
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
146
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
147
+ end
148
+
149
+ def clean
150
+ return unless File.exist?(MARKER_FILE)
151
+
152
+ brew = HomebrewPath.path
153
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
154
+ system("#{brew} uninstall #{BREW_NAME}")
155
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
156
+ end
157
+ end
158
+ end
159
+
160
+ # libyaml library installation Section
161
+ class InstallLibyaml < Taski::Section
162
+ interfaces :lib_path
163
+
164
+ def impl
165
+ brew = HomebrewPath.path
166
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
167
+ end
168
+
169
+ BREW_NAME = 'libyaml'
170
+ MARKER_FILE = File.expand_path('~/.kompo_installed_libyaml')
171
+
172
+ class Installed < Taski::Task
173
+ def run
174
+ brew = HomebrewPath.path
175
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
176
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
177
+ puts "#{BREW_NAME} is already installed"
178
+ end
179
+ end
180
+
181
+ class Install < Taski::Task
182
+ def run
183
+ brew = HomebrewPath.path
184
+ puts "Installing #{BREW_NAME}..."
185
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
186
+ File.write(MARKER_FILE, 'installed')
187
+
188
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
189
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
190
+ end
191
+
192
+ def clean
193
+ return unless File.exist?(MARKER_FILE)
194
+
195
+ brew = HomebrewPath.path
196
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
197
+ system("#{brew} uninstall #{BREW_NAME}")
198
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
199
+ end
200
+ end
201
+ end
202
+
203
+ # zlib library installation Section
204
+ class InstallZlib < Taski::Section
205
+ interfaces :lib_path
206
+
207
+ def impl
208
+ brew = HomebrewPath.path
209
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
210
+ end
211
+
212
+ BREW_NAME = 'zlib'
213
+ MARKER_FILE = File.expand_path('~/.kompo_installed_zlib')
214
+
215
+ class Installed < Taski::Task
216
+ def run
217
+ brew = HomebrewPath.path
218
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
219
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
220
+ puts "#{BREW_NAME} is already installed"
221
+ end
222
+ end
223
+
224
+ class Install < Taski::Task
225
+ def run
226
+ brew = HomebrewPath.path
227
+ puts "Installing #{BREW_NAME}..."
228
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
229
+ File.write(MARKER_FILE, 'installed')
230
+
231
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
232
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
233
+ end
234
+
235
+ def clean
236
+ return unless File.exist?(MARKER_FILE)
237
+
238
+ brew = HomebrewPath.path
239
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
240
+ system("#{brew} uninstall #{BREW_NAME}")
241
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
242
+ end
243
+ end
244
+ end
245
+
246
+ # libffi library installation Section
247
+ class InstallLibffi < Taski::Section
248
+ interfaces :lib_path
249
+
250
+ def impl
251
+ brew = HomebrewPath.path
252
+ system("#{brew} list #{BREW_NAME} > /dev/null 2>&1") ? Installed : Install
253
+ end
254
+
255
+ BREW_NAME = 'libffi'
256
+ MARKER_FILE = File.expand_path('~/.kompo_installed_libffi')
257
+
258
+ class Installed < Taski::Task
259
+ def run
260
+ brew = HomebrewPath.path
261
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
262
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
263
+ puts "#{BREW_NAME} is already installed"
264
+ end
265
+ end
266
+
267
+ class Install < Taski::Task
268
+ def run
269
+ brew = HomebrewPath.path
270
+ puts "Installing #{BREW_NAME}..."
271
+ system("#{brew} install #{BREW_NAME}") or raise "Failed to install #{BREW_NAME}"
272
+ File.write(MARKER_FILE, 'installed')
273
+
274
+ prefix = `#{brew} --prefix #{BREW_NAME} 2>/dev/null`.chomp
275
+ @lib_path = "-L#{prefix}/lib" if $CHILD_STATUS.success? && !prefix.empty?
276
+ end
277
+
278
+ def clean
279
+ return unless File.exist?(MARKER_FILE)
280
+
281
+ brew = HomebrewPath.path
282
+ puts "Uninstalling #{BREW_NAME} (installed by kompo)..."
283
+ system("#{brew} uninstall #{BREW_NAME}")
284
+ File.delete(MARKER_FILE) if File.exist?(MARKER_FILE)
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ # Linux implementation - checks dependencies using pkg-config
291
+ class ForLinux < Taski::Task
292
+ def run
293
+ unless pkg_config_available?
294
+ puts '[WARNING] pkg-config not found. Skipping dependency check.'
295
+ puts 'Install pkg-config to enable automatic dependency verification.'
296
+ @lib_paths = ''
297
+ return
298
+ end
299
+
300
+ check_dependencies
301
+ @lib_paths = collect_lib_paths
302
+
303
+ puts 'All required development libraries are installed.'
304
+ end
305
+
306
+ REQUIRED_LIBS = {
307
+ 'openssl' => { pkg_config: 'openssl', apt: 'libssl-dev', yum: 'openssl-devel' },
308
+ 'readline' => { pkg_config: 'readline', apt: 'libreadline-dev', yum: 'readline-devel' },
309
+ 'zlib' => { pkg_config: 'zlib', apt: 'zlib1g-dev', yum: 'zlib-devel' },
310
+ 'libyaml' => { pkg_config: 'yaml-0.1', apt: 'libyaml-dev', yum: 'libyaml-devel' },
311
+ 'libffi' => { pkg_config: 'libffi', apt: 'libffi-dev', yum: 'libffi-devel' }
312
+ }.freeze
313
+
314
+ private
315
+
316
+ def pkg_config_available?
317
+ system('which pkg-config > /dev/null 2>&1')
318
+ end
319
+
320
+ def check_dependencies
321
+ missing = REQUIRED_LIBS.reject do |_, info|
322
+ system("pkg-config --exists #{info[:pkg_config]} 2>/dev/null")
323
+ end
324
+
325
+ raise build_error_message(missing) unless missing.empty?
326
+ end
327
+
328
+ def collect_lib_paths
329
+ pkg_names = REQUIRED_LIBS.values.map { |info| info[:pkg_config] }
330
+ paths = pkg_names.flat_map do |pkg|
331
+ `pkg-config --libs-only-L #{pkg} 2>/dev/null`.chomp.split
332
+ end
333
+ paths.uniq.join(' ')
334
+ end
335
+
336
+ def build_error_message(missing)
337
+ lib_names = missing.keys.join(', ')
338
+ apt_packages = missing.values.map { |info| info[:apt] }.join(' ')
339
+ yum_packages = missing.values.map { |info| info[:yum] }.join(' ')
340
+
341
+ <<~MSG
342
+ Missing required development libraries: #{lib_names}
343
+
344
+ Please install them using your package manager:
345
+
346
+ Ubuntu/Debian:
347
+ sudo apt-get update
348
+ sudo apt-get install -y #{apt_packages}
349
+
350
+ RHEL/CentOS/Fedora:
351
+ sudo yum install -y #{yum_packages}
352
+ # or: sudo dnf install -y #{yum_packages}
353
+
354
+ After installing, run kompo again.
355
+ MSG
356
+ end
357
+ end
358
+
359
+ private
360
+
361
+ def macos?
362
+ RUBY_PLATFORM.include?('darwin')
363
+ end
364
+ end
365
+ end