rcee_precompiled 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1433303a861ccdca59314c39762f30c11817241057c5deceb1fd90a192119c2f
4
- data.tar.gz: aa0690709c7d77f1517714e323d1cbd627febebbb29952b1c9e1ecf3e8e3bfd5
3
+ metadata.gz: 80a6876c836d53fcde0cdcc9b6b948419be41fcc942f8add855984fdcabe99aa
4
+ data.tar.gz: 52b74c8bb35c6dfd33fa1f7fbb30aa1f7e43b7b8fda8ebcd4c885837413ba5bc
5
5
  SHA512:
6
- metadata.gz: 62422e6214c2d6f7c025a7474a46a8fe42d3244125f23b9e1b44c7a4546540860ea0e7a58892dd97627f9854882f87da8e384f540be269966d2676541c170215
7
- data.tar.gz: 1ea4fe394233270e1f362b9849189e400726379448472275ce547614d4db5c76e0532ea0e00d807dd50012319623342ce97ae69408237c8690746eae2b3f9301
6
+ metadata.gz: c8864cdae0e60f649af23b3cd5b31ca7675ee8b3ab5c73edb783351d2ba09bc33d61145c86fae21b98da8ebdaad0b4e4327d717ef6665b6c87952cab4ec77d31
7
+ data.tar.gz: 47f13c358c3b04d3b47d86424e5f21b945feedbce55c9063f5521b1b10c8fc166b2763d071156391a5eae56657e5519d92b320e53d3d5cb29d9add1d15989806
data/Gemfile CHANGED
@@ -8,6 +8,6 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rake-compiler"
11
- gem "rake-compiler-dock"
11
+ gem "rake-compiler-dock", "1.5.0.rc1"
12
12
 
13
13
  gem "minitest", "~> 5.0"
data/README.md CHANGED
@@ -26,8 +26,16 @@ This is really powerful stuff, and once we assume that we can cross-compile reli
26
26
  First, we need to add some features to our `Rake::ExtensionTask` in `Rakefile`:
27
27
 
28
28
  ``` ruby
29
- cross_rubies = ["3.0.0", "2.7.0", "2.6.0", "2.5.0"]
30
- cross_platforms = ["x64-mingw32", "x86_64-linux", "x86_64-darwin", "arm64-darwin"]
29
+ cross_rubies = ["3.3.0", "3.2.0", "3.1.0", "3.0.0"]
30
+ cross_platforms = [
31
+ "x64-mingw32",
32
+ "x64-mingw-ucrt",
33
+ "x86-linux",
34
+ "x86_64-linux",
35
+ "aarch64-linux",
36
+ "x86_64-darwin",
37
+ "arm64-darwin",
38
+ ]
31
39
  ENV["RUBY_CC_VERSION"] = cross_rubies.join(":")
32
40
 
33
41
  Rake::ExtensionTask.new("precompiled", rcee_precompiled_spec) do |ext|
@@ -84,30 +92,33 @@ The top task (or, really, _set_ of tasks) runs on the host system, and invokes t
84
92
  Changes to the `extconf.rb`:
85
93
 
86
94
  ``` ruby
87
- ENV["CC"] = RbConfig::CONFIG["CC"]
95
+ def configure_cross_compilers
96
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
97
+ ENV["CC"] = RbConfig::CONFIG["CC"]
98
+ end
88
99
  ```
89
100
 
90
101
  This makes sure that the cross-compiler is the compiler used within the guest container (and not the native linux compiler).
91
102
 
92
103
  ``` ruby
93
- cross_build_p = enable_config("cross-build")
104
+ def cross_build?
105
+ enable_config("cross-build")
106
+ end
94
107
  ```
95
108
 
96
109
  The cross-compile rake task signals to `extconf.rb` that it's cross-compiling by using a commandline flag that we can inspect. We'll need this for `libyaml` to make sure that set the appropriate flags during precompilation (flags which shouldn't be set when compiling natively).
97
110
 
98
111
  ``` ruby
99
- MiniPortile.new("yaml", "0.2.5").tap do |recipe|
100
- # ...
101
- # configure the environment that MiniPortile will use for subshells
102
- ENV.to_h.dup.tap do |env|
103
- # -fPIC is necessary for linking into a shared library
104
- env["CFLAGS"] = [env["CFLAGS"], "-fPIC"].join(" ")
105
- env["SUBDIRS"] = "include src" # libyaml: skip tests
106
-
107
- recipe.configure_options += env.map { |key, value| "#{key}=#{value.strip}" }
112
+ # pass some environment variables to the libyaml configuration for cross-compilation
113
+ if cross_build?
114
+ ENV.to_h.tap do |env|
115
+ # -fPIC is necessary for linking into a shared library
116
+ env["CFLAGS"] = [env["CFLAGS"], "-fPIC"].join(" ")
117
+ env["SUBDIRS"] = "include src" # libyaml: skip tests
118
+
119
+ recipe.configure_options += env.map { |key, value| "#{key}=#{value.strip}" }
120
+ end
108
121
  end
109
- # ...
110
- end
111
122
  ```
112
123
 
113
124
  The rest of the extconf changes are related to configuring libyaml at build time. We need to set the -fPIC option so we can mix static and shared libraries together. (This should probably always be set.)
@@ -120,13 +131,13 @@ We have one more small change we'll need to make to how the extension is require
120
131
  lib
121
132
  └── rcee
122
133
  ├── precompiled
123
- │   ├── 2.5
134
+ │   ├── 3.0
124
135
  │   │   └── precompiled.so
125
- │   ├── 2.6
136
+ │   ├── 3.1
126
137
  │   │   └── precompiled.so
127
- │   ├── 2.7
138
+ │   ├── 3.2
128
139
  │   │   └── precompiled.so
129
- │   ├── 3.0
140
+ │   ├── 3.3
130
141
  │   │   └── precompiled.so
131
142
  │   └── version.rb
132
143
  └── precompiled.rb
@@ -176,7 +187,7 @@ This strategy isn't perfect. Remember what I said earlier, that a compiled C ext
176
187
  - the machine architecture (e.g., x86_64)
177
188
  - the system libraries
178
189
 
179
- The precompiled strategy mostly takes care of the first two, but there are still edge cases for system libraries. The big gotcha is that linux libc is not the same as linux musl, and we've had to work around this a few times in Nokogiri. Note also that we're unable to easily test `musl` systems on Github Actions because of limitations in the `download-artifact` action.
190
+ The precompiled strategy mostly takes care of the first two, but there are still edge cases for system libraries. The big gotcha is that linux libc is not the same as linux musl, and we've had to work around this a few times in Nokogiri.
180
191
 
181
192
  I'm positive that there are more edge cases that will be found as users add more platforms and as more gems start precompiling. I'm willing to bet money that you can break this by setting some Ruby compile-time flags on your system. I'm honestly surprised it works as well as it has. (Worth noting: the `sassc` gem stopped shipping native gems for linux because of the musl incompatibilities.)
182
193
 
data/Rakefile CHANGED
@@ -6,13 +6,26 @@ require "rake/testtask"
6
6
  require "rake/extensiontask"
7
7
  require "rake_compiler_dock"
8
8
 
9
- cross_rubies = ["3.0.0", "2.7.0", "2.6.0", "2.5.0"]
10
- cross_platforms = ["x64-mingw32", "x86_64-linux", "x86_64-darwin", "arm64-darwin"]
9
+ cross_rubies = ["3.3.0", "3.2.0", "3.1.0", "3.0.0"]
10
+ cross_platforms = [
11
+ "aarch64-linux",
12
+ "aarch64-linux-musl",
13
+ "arm-linux",
14
+ "arm-linux-musl",
15
+ "arm64-darwin",
16
+ "x64-mingw-ucrt",
17
+ "x64-mingw32",
18
+ "x86-linux",
19
+ "x86-linux-musl",
20
+ "x86_64-darwin",
21
+ "x86_64-linux",
22
+ "x86_64-linux-musl",
23
+ ]
11
24
  ENV["RUBY_CC_VERSION"] = cross_rubies.join(":")
12
25
 
13
26
  rcee_precompiled_spec = Bundler.load_gemspec("rcee_precompiled.gemspec")
14
27
  Gem::PackageTask.new(rcee_precompiled_spec).define #packaged_tarball version of the gem for platform=ruby
15
- task "package" => cross_platforms.map { |p| "gem:#{p}" } # "package" task for all the native platforms
28
+ task "package" => "gem:all"
16
29
 
17
30
  Rake::TestTask.new(:test) do |t|
18
31
  t.libs << "test"
@@ -1,41 +1,78 @@
1
1
  require "mkmf"
2
2
  require "mini_portile2"
3
3
 
4
- package_root_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
4
+ module RCEE
5
+ module Precompiled
6
+ module ExtConf
7
+ PACKAGE_ROOT_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
5
8
 
6
- RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
7
- ENV["CC"] = RbConfig::CONFIG["CC"]
9
+ class << self
10
+ def configure
11
+ configure_cross_compilers
12
+ configure_packaged_libraries
13
+ create_makefile("rcee/precompiled/precompiled")
14
+ end
8
15
 
9
- cross_build_p = enable_config("cross-build")
16
+ def configure_cross_compilers
17
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
18
+ ENV["CC"] = RbConfig::CONFIG["CC"]
19
+ end
10
20
 
11
- MiniPortile.new("yaml", "0.2.5").tap do |recipe|
12
- recipe.files = [{
13
- url: "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz",
14
- sha256: "c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4",
15
- }]
16
- recipe.target = File.join(package_root_dir, "ports")
21
+ def configure_packaged_libraries
22
+ recipe = libyaml_recipe
17
23
 
18
- # configure the environment that MiniPortile will use for subshells
19
- if cross_build_p
20
- ENV.to_h.tap do |env|
21
- # -fPIC is necessary for linking into a shared library
22
- env["CFLAGS"] = [env["CFLAGS"], "-fPIC"].join(" ")
23
- env["SUBDIRS"] = "include src" # libyaml: skip tests
24
+ # pass some environment variables to the libyaml configuration for cross-compilation
25
+ if cross_build?
26
+ ENV.to_h.tap do |env|
27
+ # -fPIC is necessary for linking into a shared library
28
+ env["CFLAGS"] = [env["CFLAGS"], "-fPIC"].join(" ")
29
+ env["SUBDIRS"] = "include src" # libyaml: skip tests
24
30
 
25
- recipe.configure_options += env.map { |key, value| "#{key}=#{value.strip}" }
26
- end
27
- end
31
+ recipe.configure_options += env.map { |key, value| "#{key}=#{value.strip}" }
32
+ end
33
+ end
28
34
 
29
- unless File.exist?(File.join(recipe.target, recipe.host, recipe.name, recipe.version))
30
- recipe.cook
31
- end
35
+ # ensure libyaml has already been unpacked, configured, and compiled
36
+ unless File.exist?(File.join(recipe.target, recipe.host, recipe.name, recipe.version))
37
+ recipe.cook
38
+ end
39
+
40
+ # use the packaged libyaml
41
+ recipe.activate
42
+ pkg_config(File.join(recipe.path, "lib", "pkgconfig", "yaml-0.1.pc"))
43
+
44
+ # assert that we can build against the packaged libyaml
45
+ unless have_library("yaml", "yaml_get_version", "yaml.h")
46
+ abort("\nERROR: *** could not find libyaml development environment ***\n\n")
47
+ end
48
+ end
32
49
 
33
- recipe.activate
34
- pkg_config(File.join(recipe.path, "lib", "pkgconfig", "yaml-0.1.pc"))
50
+ def cross_build?
51
+ enable_config("cross-build")
52
+ end
53
+
54
+ def download
55
+ libyaml_recipe.download
56
+ end
57
+
58
+ def libyaml_recipe
59
+ MiniPortile.new("yaml", "0.2.5").tap do |recipe|
60
+ recipe.files = [{
61
+ url: "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz",
62
+ sha256: "c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
63
+ }]
64
+ recipe.target = File.join(PACKAGE_ROOT_DIR, "ports")
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
35
70
  end
36
71
 
37
- unless have_library("yaml", "yaml_get_version", "yaml.h")
38
- abort("\nERROR: *** could not find libyaml development environment ***\n\n")
72
+ # run "ruby ./ext/precompiled/extconf.rb -- --download-dependencies" to download the tarball
73
+ if arg_config("--download-dependencies")
74
+ RCEE::Precompiled::ExtConf.download
75
+ exit!(0)
39
76
  end
40
77
 
41
- create_makefile("rcee/precompiled/precompiled")
78
+ RCEE::Precompiled::ExtConf.configure
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RCEE
4
4
  module Precompiled
5
- VERSION = "0.3.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.summary = "Example gem demonstrating a basic C extension."
16
16
  spec.description = "Part of a project to explain how Ruby C extensions work."
17
17
  spec.homepage = "https://github.com/flavorjones/ruby-c-extensions-explained"
18
- spec.required_ruby_version = ">= 2.5.0"
18
+ spec.required_ruby_version = ">= 3.0.0"
19
19
  spec.license = "MIT"
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcee_precompiled
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Dalessio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-08 00:00:00.000000000 Z
11
+ date: 2024-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mini_portile2
@@ -24,6 +24,7 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ force_ruby_platform: false
27
28
  description: Part of a project to explain how Ruby C extensions work.
28
29
  email:
29
30
  - mike.dalessio@gmail.com
@@ -55,14 +56,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
56
  requirements:
56
57
  - - ">="
57
58
  - !ruby/object:Gem::Version
58
- version: 2.5.0
59
+ version: 3.0.0
59
60
  required_rubygems_version: !ruby/object:Gem::Requirement
60
61
  requirements:
61
62
  - - ">="
62
63
  - !ruby/object:Gem::Version
63
64
  version: '0'
64
65
  requirements: []
65
- rubygems_version: 3.2.22
66
+ rubygems_version: 3.4.19
66
67
  signing_key:
67
68
  specification_version: 4
68
69
  summary: Example gem demonstrating a basic C extension.