gem-ext-zig_builder 0.2.1 → 0.3.0

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: 55b4bf2fe202be13789c3afbc3fc71d515d49f56b08b92720cd882ebed52d13d
4
- data.tar.gz: 7fee2a3b6f222b25ce72b95275cdb8be2b2c61ca0948a44ae12f4d5098649e77
3
+ metadata.gz: 352295a2ed859fecfef121e9b8748b10efaa83eb2cc14842307cd43779c21724
4
+ data.tar.gz: 6222bdbd160014d6cf7c0e060a49d9ce9da9e8f37b4e774937ea3f7da0b912a9
5
5
  SHA512:
6
- metadata.gz: 38802825ac0b746613ef0fba7447db7cda21879eaef100307689a083e3f05640ccea6adce95f2805b0d5ce2af2150fc1a21a06b1b769a0f2875c060a62cba970
7
- data.tar.gz: 570fd46fc68606563c097b858e763ea92564d3189e6bba9f43971ea591403bd4561033fbe073afafd5318d16b2c5d095abf672a0e45119b0d30f7f949e6aaf54
6
+ metadata.gz: f38796b73f8c45131a5b0b6281304f2b8e5b76d2aab3a50bac322843794f24af60adea60c0a4ff295a24d9ebde9d8eba90a1f4966a999c0379abb125164c915d
7
+ data.tar.gz: 727f9954335613743bbd4dceaf35e7d359c4fa0bb5759c109323a1f6ad679e11a7d68446c13d5ae3771b2e5fb9fb40278f035163010b10660423883b38af0b80
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gem
2
4
  module Ext
3
5
  class Builder; end
6
+
4
7
  class ZigBuilder < Builder
5
- VERSION = '0.2.1'
8
+ VERSION = '0.3.0'
6
9
  end
7
10
  end
8
11
  end
@@ -1,54 +1,141 @@
1
1
  # frozen_string_literal: true
2
- require 'gem/ext/zig_builder/version'
2
+
3
+ require_relative 'zig_builder/version'
3
4
  require 'rubygems/ext/builder'
4
- require 'rubygems/command'
5
- require 'shellwords'
6
5
  require 'rbconfig'
7
6
  require 'tmpdir'
8
7
 
8
+ # This class is used by rubygems to build Zig extensions. It is a thin-wrapper
9
+ # over the zig build command. To trigger this builder, specify a build.zig
10
+ # file in the gem spec.
11
+ #
12
+ # A minimal zig.build example:
13
+ #
14
+ # const std = @import("std");
15
+ # pub fn build(b: *std.Build) void {
16
+ # const optimize = b.standardOptimizeOption(.{});
17
+ # const target = b.standardTargetOptions(.{});
18
+ # const lib = b.addSharedLibrary(.{
19
+ # .name = "zigrb_example",
20
+ # .root_source_file = .{ .path = "src/zigrb.zig" },
21
+ # .target = target,
22
+ # .optimize = optimize,
23
+ # });
24
+ # lib.linkSystemLibrary(std.os.getenv("RUBY_PC") orelse "ruby");
25
+ # lib.linkSystemLibrary("c");
26
+ # b.installArtifact(lib);
27
+ # }
28
+ #
29
+ # A minimal zigrb.zig example:
30
+ #
31
+ # const std = @import("std");
32
+ # const ruby = @cImport(@cInclude("ruby/ruby.h"));
33
+ # export fn Init_libzigrb_example() void {
34
+ # ruby.ruby_init();
35
+ # }
36
+ #
37
+ # An example of defining a ruby class and adding a zig method:
38
+ #
39
+ # var zig_rb_class: ruby.VALUE = ruby.rb_define_class("ZigExample", ruby.rb_cObject);
40
+ # _ = ruby.rb_define_method(zig_rb_class, "method_name", rb_example_method, 2);
41
+ #
42
+ # An example of a zig ruby method:
43
+ #
44
+ # fn rb_example_method(...) callconv(.C) ruby.VALUE {
45
+ # var ap = @cVaStart();
46
+ # defer @cVaEnd(&ap);
47
+ # // first argument is `self` in ruby; discard it
48
+ # var self = @cVaArg(&ap, ruby.VALUE); _ = self;
49
+ # // additional arguments
50
+ # var _ = @cVaArg(&ap, ruby.VALUE);
51
+ # var _ = @cVaArg(&ap, ruby.VALUE);
52
+ # return ruby.QNil
53
+ # }
54
+ #
55
+ # An example of ruby zig type conversions:
56
+ #
57
+ # var m = ruby.NUM2INT(@cVaArg(&ap, ruby.VALUE));
58
+ # var n = ruby.NUM2INT(@cVaArg(&ap, ruby.VALUE));
59
+ # return ruby.INT2NUM(f(m, n));
60
+ #
9
61
  class Gem::Ext::ZigBuilder < Gem::Ext::Builder
62
+ #
63
+ # This module patches the Builder builder_for method to ensure that
64
+ # this builder class is used for build.zig extensions.
65
+ #
10
66
  module PatchBuilderLookup
11
67
  def builder_for(extension)
12
68
  /build.zig/ === extension ? Gem::Ext::ZigBuilder : super
13
69
  end
14
70
  end
15
71
 
16
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=nil)
17
- tmp_dir = Dir.mktmpdir
18
- dlext = RbConfig::CONFIG['DLEXT']
19
- target_vendor = RbConfig::CONFIG['target_vendor']
20
- pkg_config_path = "#{RbConfig::CONFIG['libdir']}/pkgconfig"
21
- ruby_pc = "#{File.basename(RbConfig::CONFIG['ruby_pc'], '.pc')}"
22
-
23
- cmd = [].tap {|c|
24
- c << 'zig' << 'build' << '-Doptimize=ReleaseSafe'
25
- c << '--prefix-lib-dir' << tmp_dir
26
- c << 'test' << 'install'
27
- }
28
-
29
- # older versions of ruby do not support the 5th `env` argument to run,
30
- # so pollute the global ENV as a cheap workaround
31
- ENV['PKG_CONFIG_PATH'] = pkg_config_path
32
- ENV['RUBY_PC' ] = ruby_pc
33
-
34
- # even older versions of ruby do not support the 4th extension_dir arg
35
- Dir.chdir(extension_dir ? extension_dir : '.') do
36
- run(cmd, results, 'zig')
72
+ class << self
73
+ def build(_extension, dest_path, results, _args = [], _lib_dir = nil, extension_dir = nil)
74
+ dlext = RbConfig::CONFIG['DLEXT']
75
+ tmp_dir = Dir.mktmpdir
76
+ command = _build_command(tmp_dir)
77
+ envvars = _build_envvars
78
+
79
+ _run(command, results, 'zig', extension_dir, envvars)
80
+ _install_artifacts(tmp_dir, dlext, dest_path)
81
+
82
+ results
83
+ ensure
84
+ FileUtils.remove_entry tmp_dir if tmp_dir
37
85
  end
38
86
 
39
- Dir.chdir tmp_dir do
40
- if target_vendor == 'apple' && dlext == 'bundle'
41
- Dir.glob('*.dylib').each do |dylib|
42
- FileUtils.mv dylib, "#{File.basename(dylib, '.dylib')}.bundle"
43
- end
87
+ private
88
+
89
+ def _build_command(tmp_dir)
90
+ [].tap { |c|
91
+ c << 'zig' << 'build' << '-Doptimize=ReleaseSafe'
92
+ c << '--prefix-lib-dir' << tmp_dir
93
+ c << 'test' << 'install'
94
+ }
95
+ end
96
+
97
+ def _build_envvars
98
+ {
99
+ 'PKG_CONFIG_PATH' => "#{RbConfig::CONFIG['libdir']}/pkgconfig",
100
+ 'RUBY_PC' => File.basename(RbConfig::CONFIG['ruby_pc'], '.pc'),
101
+ }
102
+ end
103
+
104
+ def _run(command, results, command_name, dir, env)
105
+ # old versions do not support the 4th `dir` arg
106
+ # old versions do not support the 5th `env` arg
107
+ case method(:run).parameters.count
108
+ when 3
109
+ _pollute_env(env)
110
+ run(command, results, command_name)
111
+ when 4
112
+ _pollute_env(env)
113
+ run(command, results, command_name, dir)
114
+ when 5
115
+ run(command, results, command_name, dir, env)
116
+ else
117
+ raise ArgumentError, 'wrong number of arguments'
44
118
  end
119
+ end
45
120
 
46
- FileUtils.mv Dir.glob("*.#{dlext}"), dest_path
121
+ def _pollute_env(env)
122
+ env.each do |k, v| ENV[k] = v end
47
123
  end
48
124
 
49
- results
50
- ensure
51
- FileUtils.remove_entry tmp_dir if tmp_dir
125
+ def _install_artifacts(tmp_dir, dlext, dest_path)
126
+ target_vendor = RbConfig::CONFIG['target_vendor']
127
+
128
+ Dir.chdir tmp_dir do
129
+ if target_vendor == 'apple' && dlext == 'bundle'
130
+ # zig builds a .dylib but ruby wants to load a .bundle
131
+ Dir.glob('*.dylib').each do |dylib|
132
+ FileUtils.mv dylib, "#{File.basename(dylib, '.dylib')}.bundle"
133
+ end
134
+ end
135
+
136
+ FileUtils.mv Dir.glob("*.#{dlext}"), dest_path
137
+ end
138
+ end
52
139
  end
53
140
  end
54
141
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RubyGems will load plugins in the latest version of each installed gem
4
+ # or $LOAD_PATH. Plugins must be named ‘rubygems_plugin’ (.rb, .so,
5
+ # etc) and placed at the root of your gem’s #require_path. Plugins are
6
+ # installed at a special location and loaded on boot.
7
+ # https://guides.rubygems.org/plugins/
8
+
9
+ require_relative 'gem/ext/zig_builder'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem-ext-zig_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank J. Cameron
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-11 00:00:00.000000000 Z
11
+ date: 2023-05-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: ''
14
14
  email:
@@ -19,6 +19,7 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - lib/gem/ext/zig_builder.rb
21
21
  - lib/gem/ext/zig_builder/version.rb
22
+ - lib/rubygems_plugin.rb
22
23
  homepage: https://gitlab.com/fjc/gem-ext-zig_builder
23
24
  licenses:
24
25
  - MIT
@@ -26,6 +27,7 @@ metadata:
26
27
  homepage_uri: https://gitlab.com/fjc/gem-ext-zig_builder
27
28
  source_code_uri: https://gitlab.com/fjc/gem-ext-zig_builder
28
29
  changelog_uri: https://gitlab.com/fjc/gem-ext-zig_builder
30
+ rubygems_mfa_required: 'true'
29
31
  post_install_message:
30
32
  rdoc_options: []
31
33
  require_paths:
@@ -34,7 +36,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
34
36
  requirements:
35
37
  - - ">="
36
38
  - !ruby/object:Gem::Version
37
- version: 2.3.0
39
+ version: 2.5.0
38
40
  required_rubygems_version: !ruby/object:Gem::Requirement
39
41
  requirements:
40
42
  - - ">="