pyroscope 0.1.1 → 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,12 @@
1
+ extern crate cbindgen;
2
+
3
+ use cbindgen::Config;
4
+
5
+ fn main() {
6
+ let bindings = {
7
+ let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
8
+ let config = Config::from_file("cbindgen.toml").unwrap();
9
+ cbindgen::generate_with_config(&crate_dir, config).unwrap()
10
+ };
11
+ bindings.write_to_file("include/rbspy.h");
12
+ }
@@ -0,0 +1,22 @@
1
+ # The language to output bindings in
2
+ language = "C"
3
+ documentation_style = "C"
4
+
5
+ style = "type"
6
+
7
+ # An optional name to use as an include guard
8
+ include_guard = "RBSPY_H_"
9
+ # include a comment with the version of cbindgen used to generate the file
10
+ include_version = true
11
+
12
+ # An optional string of text to output at the beginning of the generated file
13
+ header = "/* Licensed under Apache-2.0 */"
14
+ autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
15
+
16
+ braces = "SameLine"
17
+ tab_width = 2
18
+ line_length = 80
19
+
20
+ [parse]
21
+ # Do not parse dependent crates
22
+ parse_deps = false
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+ require 'rake'
3
+
4
+ create_makefile('rbspy')
5
+
6
+ app = Rake.application
7
+ app.init
8
+ app.add_import 'Rakefile'
9
+ app.load_rakefile
10
+
11
+ app['default'].invoke
@@ -0,0 +1,183 @@
1
+ use ffikit::Signal;
2
+ use pyroscope::backend::Tag;
3
+ use pyroscope::PyroscopeAgent;
4
+ use pyroscope_rbspy::{rbspy_backend, RbspyConfig};
5
+ use std::collections::hash_map::DefaultHasher;
6
+ use std::ffi::CStr;
7
+ use std::hash::Hasher;
8
+ use std::os::raw::c_char;
9
+
10
+ #[no_mangle]
11
+ pub extern "C" fn initialize_agent(
12
+ application_name: *const c_char, server_address: *const c_char, auth_token: *const c_char,
13
+ sample_rate: u32, detect_subprocesses: bool, on_cpu: bool, report_pid: bool,
14
+ report_thread_id: bool, tags: *const c_char,
15
+ ) -> bool {
16
+ // Initialize FFIKit
17
+ let recv = ffikit::initialize_ffi().unwrap();
18
+
19
+ let application_name = unsafe { CStr::from_ptr(application_name) }
20
+ .to_str()
21
+ .unwrap()
22
+ .to_string();
23
+
24
+ let server_address = unsafe { CStr::from_ptr(server_address) }
25
+ .to_str()
26
+ .unwrap()
27
+ .to_string();
28
+
29
+ let auth_token = unsafe { CStr::from_ptr(auth_token) }
30
+ .to_str()
31
+ .unwrap()
32
+ .to_string();
33
+
34
+ let tags_string = unsafe { CStr::from_ptr(tags) }
35
+ .to_str()
36
+ .unwrap()
37
+ .to_string();
38
+
39
+ let pid = std::process::id();
40
+
41
+ let rbspy_config = RbspyConfig::new(pid.try_into().unwrap())
42
+ .sample_rate(sample_rate)
43
+ .lock_process(false)
44
+ .with_subprocesses(detect_subprocesses)
45
+ .on_cpu(on_cpu)
46
+ .report_pid(report_pid)
47
+ .report_thread_id(report_thread_id);
48
+
49
+ let tags_ref = tags_string.as_str();
50
+ let tags = string_to_tags(tags_ref);
51
+ let rbspy = rbspy_backend(rbspy_config);
52
+
53
+ let mut agent_builder = PyroscopeAgent::builder(server_address, application_name)
54
+ .backend(rbspy)
55
+ .tags(tags);
56
+
57
+ if auth_token != "" {
58
+ agent_builder = agent_builder.auth_token(auth_token);
59
+ }
60
+
61
+ let agent = agent_builder.build().unwrap();
62
+
63
+ let agent_running = agent.start().unwrap();
64
+
65
+ std::thread::spawn(move || {
66
+ while let Ok(signal) = recv.recv() {
67
+ match signal {
68
+ Signal::Kill => {
69
+ agent_running.stop().unwrap();
70
+ break;
71
+ }
72
+ Signal::AddGlobalTag(name, value) => {
73
+ agent_running.add_global_tag(Tag::new(name, value)).unwrap();
74
+ }
75
+ Signal::RemoveGlobalTag(name, value) => {
76
+ agent_running
77
+ .remove_global_tag(Tag::new(name, value))
78
+ .unwrap();
79
+ }
80
+ Signal::AddThreadTag(thread_id, key, value) => {
81
+ let tag = Tag::new(key, value);
82
+ agent_running.add_thread_tag(thread_id, tag).unwrap();
83
+ }
84
+ Signal::RemoveThreadTag(thread_id, key, value) => {
85
+ let tag = Tag::new(key, value);
86
+ agent_running.remove_thread_tag(thread_id, tag).unwrap();
87
+ }
88
+ }
89
+ }
90
+ });
91
+
92
+ true
93
+ }
94
+
95
+ #[no_mangle]
96
+ pub extern "C" fn drop_agent() -> bool {
97
+ // Send Kill signal to the FFI merge channel.
98
+ ffikit::send(ffikit::Signal::Kill).unwrap();
99
+
100
+ true
101
+ }
102
+
103
+ #[no_mangle]
104
+ pub extern "C" fn add_thread_tag(thread_id: u64, key: *const c_char, value: *const c_char) -> bool {
105
+ let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
106
+ let value = unsafe { CStr::from_ptr(value) }
107
+ .to_str()
108
+ .unwrap()
109
+ .to_owned();
110
+
111
+ let pid = std::process::id();
112
+ let mut hasher = DefaultHasher::new();
113
+ hasher.write_u64(thread_id % pid as u64);
114
+ let id = hasher.finish();
115
+
116
+ ffikit::send(ffikit::Signal::AddThreadTag(id, key, value)).unwrap();
117
+
118
+ true
119
+ }
120
+
121
+ #[no_mangle]
122
+ pub extern "C" fn remove_thread_tag(
123
+ thread_id: u64, key: *const c_char, value: *const c_char,
124
+ ) -> bool {
125
+ let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
126
+ let value = unsafe { CStr::from_ptr(value) }
127
+ .to_str()
128
+ .unwrap()
129
+ .to_owned();
130
+
131
+ let pid = std::process::id();
132
+ let mut hasher = DefaultHasher::new();
133
+ hasher.write_u64(thread_id % pid as u64);
134
+ let id = hasher.finish();
135
+
136
+ ffikit::send(ffikit::Signal::RemoveThreadTag(id, key, value)).unwrap();
137
+
138
+ true
139
+ }
140
+
141
+ #[no_mangle]
142
+ pub extern "C" fn add_global_tag(key: *const c_char, value: *const c_char) -> bool {
143
+ let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
144
+ let value = unsafe { CStr::from_ptr(value) }
145
+ .to_str()
146
+ .unwrap()
147
+ .to_owned();
148
+
149
+ ffikit::send(ffikit::Signal::AddGlobalTag(key, value)).unwrap();
150
+
151
+ true
152
+ }
153
+
154
+ #[no_mangle]
155
+ pub extern "C" fn remove_global_tag(key: *const c_char, value: *const c_char) -> bool {
156
+ let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap().to_owned();
157
+ let value = unsafe { CStr::from_ptr(value) }
158
+ .to_str()
159
+ .unwrap()
160
+ .to_owned();
161
+
162
+ ffikit::send(ffikit::Signal::RemoveGlobalTag(key, value)).unwrap();
163
+
164
+ true
165
+ }
166
+
167
+ // Convert a string of tags to a Vec<(&str, &str)>
168
+ fn string_to_tags<'a>(tags: &'a str) -> Vec<(&'a str, &'a str)> {
169
+ let mut tags_vec = Vec::new();
170
+ // check if string is empty
171
+ if tags.is_empty() {
172
+ return tags_vec;
173
+ }
174
+
175
+ for tag in tags.split(',') {
176
+ let mut tag_split = tag.split('=');
177
+ let key = tag_split.next().unwrap();
178
+ let value = tag_split.next().unwrap();
179
+ tags_vec.push((key, value));
180
+ }
181
+
182
+ tags_vec
183
+ }
@@ -0,0 +1,20 @@
1
+ [package]
2
+ name = "thread_id"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ name = "thread_id"
8
+ crate-type = ["cdylib"]
9
+
10
+ [dependencies]
11
+ libc = "*"
12
+
13
+ [build-dependencies]
14
+ cbindgen = "0.20.0"
15
+
16
+ [profile.release]
17
+ opt-level= "z"
18
+ debug = false
19
+ lto = true
20
+ codegen-units = 1
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+
5
+ class ThreadIdRakeCargoHelper
6
+ attr_reader :gemname
7
+
8
+ def initialize(gemname=File.basename(__dir__))
9
+ @gemname = gemname
10
+ end
11
+
12
+ def self.command?(name)
13
+ exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
14
+ ENV["PATH"].split(File::PATH_SEPARATOR).any? do |path|
15
+ exts.any? do |ext|
16
+ exe = File.join(path, "#{name}#{ext}")
17
+ File.executable?(exe) && !File.directory?(exe)
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.rust_toolchain
23
+ # return env variable if set
24
+ target = ENV["RUST_TARGET"]
25
+ return target if target
26
+
27
+ str = `rustc --version --verbose`
28
+ info = str.lines.map {|l| l.chomp.split(/:\s+/, 2)}.drop(1).to_h
29
+ info["host"]
30
+ end
31
+
32
+ def self.cargo_target_dir
33
+ return @cargo_target_dir if defined? @cargo_target_dir
34
+
35
+ str = `cargo metadata --format-version 1 --offline --no-deps --quiet`
36
+ begin
37
+ require "json"
38
+ dir = JSON.parse(str)["target_directory"]
39
+ rescue LoadError # json is usually part of the stdlib, but just in case
40
+ /"target_directory"\s*:\s*"(?<dir>[^"]*)"/ =~ str
41
+ end
42
+ @cargo_target_dir = dir || "target"
43
+ end
44
+
45
+ def self.flags
46
+ cc_flags = Shellwords.split(RbConfig.expand(RbConfig::MAKEFILE_CONFIG["CC"].dup))
47
+
48
+ ["-C", "linker=#{cc_flags.shift}",
49
+ *cc_flags.flat_map {|a| ["-C", "link-arg=#{a}"] },
50
+ "-L", "native=#{RbConfig::CONFIG["libdir"]}",
51
+ *dld_flags,
52
+ *platform_flags]
53
+ end
54
+
55
+ def self.dld_flags
56
+ Shellwords.split(RbConfig::CONFIG["DLDFLAGS"]).flat_map do |arg|
57
+ arg = arg.gsub(/\$\((\w+)\)/) do
58
+ $1 == "DEFFILE" ? nil : RbConfig::CONFIG[name]
59
+ end.strip
60
+ next [] if arg.empty?
61
+
62
+ transform_flag(arg)
63
+ end
64
+ end
65
+
66
+ def self.platform_flags
67
+ return unless RbConfig::CONFIG["target_os"] =~ /mingw/i
68
+
69
+ [*Shellwords.split(RbConfig::CONFIG["LIBRUBYARG"]).flat_map {|arg| transform_flag(arg)},
70
+ "-C", "link-arg=-Wl,--dynamicbase",
71
+ "-C", "link-arg=-Wl,--disable-auto-image-base",
72
+ "-C", "link-arg=-static-libgcc"]
73
+ end
74
+
75
+ def self.transform_flag(arg)
76
+ k, v = arg.split(/(?<=..)/, 2)
77
+ case k
78
+ when "-L"
79
+ [k, "native=#{v}"]
80
+ when "-l"
81
+ [k, v]
82
+ when "-F"
83
+ ["-l", "framework=#{v}"]
84
+ else
85
+ ["-C", "link_arg=#{k}#{v}"]
86
+ end
87
+ end
88
+
89
+ def install_dir
90
+ File.expand_path(File.join("..", "..", "lib", gemname), __dir__)
91
+ end
92
+
93
+ def rust_name
94
+ prefix = "lib" unless Gem.win_platform?
95
+ suffix = if RbConfig::CONFIG["target_os"] =~ /darwin/i
96
+ ".dylib"
97
+ elsif Gem.win_platform?
98
+ ".dll"
99
+ else
100
+ ".so"
101
+ end
102
+ "#{prefix}#{gemname}#{suffix}"
103
+ end
104
+
105
+ def ruby_name
106
+ "#{gemname}.#{RbConfig::CONFIG["DLEXT"]}"
107
+ end
108
+
109
+ end
110
+
111
+ task default: [:thread_id_install, :thread_id_clean]
112
+ task thread_id: [:thread_id_install, :thread_id_clean]
113
+
114
+ desc "set dev mode for subsequent task, run like `rake dev install`"
115
+ task :thread_id_dev do
116
+ @dev = true
117
+ end
118
+
119
+ desc "build gem native extension and copy to lib"
120
+ task thread_id_install: [:thread_id_cd, :thread_id_build] do
121
+ helper = ThreadIdRakeCargoHelper.new
122
+ profile_dir = @dev ? "debug" : "release"
123
+ arch_dir = RbspyRakeCargoHelper.rust_toolchain
124
+ source = File.join(ThreadIdRakeCargoHelper.cargo_target_dir, arch_dir, profile_dir, helper.rust_name)
125
+ dest = File.join(helper.install_dir, helper.ruby_name)
126
+ mkdir_p(helper.install_dir)
127
+ rm(dest) if File.exist?(dest)
128
+ cp(source, dest)
129
+ end
130
+
131
+ desc "build gem native extension"
132
+ task thread_id_build: [:thread_id_cargo, :thread_id_cd] do
133
+ sh "cargo", "rustc", *(["--locked", "--release"] unless @dev), "--target=#{RbspyRakeCargoHelper.rust_toolchain}", "--", *RbspyRakeCargoHelper.flags
134
+ end
135
+
136
+ desc "clean up release build artifacts"
137
+ task thread_id_clean: [:thread_id_cargo, :thread_id_cd] do
138
+ sh "cargo clean --release"
139
+ end
140
+
141
+ desc "clean up build artifacts"
142
+ task thread_id_clobber: [:thread_id_cargo, :thread_id_cd] do
143
+ sh "cargo clean"
144
+ end
145
+
146
+ desc "check for cargo"
147
+ task :thread_id_cargo do
148
+ raise <<-MSG unless ThreadIdRakeCargoHelper.command?("cargo")
149
+ This gem requires a Rust compiler and the `cargo' build tool to build the
150
+ gem's native extension. See https://www.rust-lang.org/tools/install for
151
+ how to install Rust. `cargo' is usually part of the Rust installation.
152
+ MSG
153
+
154
+ raise <<-MSG if Gem.win_platform? && ThreadIdRakeCargoHelper.rust_toolchain !~ /gnu/
155
+ Found Rust toolchain `#{ThreadIdRakeCargoHelper.rust_toolchain}' but the gem native
156
+ extension requires the gnu toolchain on Windows.
157
+ MSG
158
+ end
159
+
160
+ # ensure task is running in the right dir
161
+ task :thread_id_cd do
162
+ cd(__dir__) unless __dir__ == pwd
163
+ end
@@ -0,0 +1,12 @@
1
+ extern crate cbindgen;
2
+
3
+ use cbindgen::Config;
4
+
5
+ fn main() {
6
+ let bindings = {
7
+ let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
8
+ let config = Config::from_file("cbindgen.toml").unwrap();
9
+ cbindgen::generate_with_config(&crate_dir, config).unwrap()
10
+ };
11
+ bindings.write_to_file("include/thread_id.h");
12
+ }
@@ -0,0 +1,22 @@
1
+ # The language to output bindings in
2
+ language = "C"
3
+ documentation_style = "C"
4
+
5
+ style = "type"
6
+
7
+ # An optional name to use as an include guard
8
+ include_guard = "RBSPY_H_"
9
+ # include a comment with the version of cbindgen used to generate the file
10
+ include_version = true
11
+
12
+ # An optional string of text to output at the beginning of the generated file
13
+ header = "/* Licensed under Apache-2.0 */"
14
+ autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
15
+
16
+ braces = "SameLine"
17
+ tab_width = 2
18
+ line_length = 80
19
+
20
+ [parse]
21
+ # Do not parse dependent crates
22
+ parse_deps = false
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+ require 'rake'
3
+
4
+ create_makefile('thread_id')
5
+
6
+ app = Rake.application
7
+ app.init
8
+ app.add_import 'Rakefile'
9
+ app.load_rakefile
10
+
11
+ app['default'].invoke
@@ -0,0 +1,4 @@
1
+ #[no_mangle]
2
+ pub extern "C" fn thread_id() -> u64 {
3
+ unsafe { libc::pthread_self() as u64 }
4
+ }
@@ -1,3 +1,3 @@
1
1
  module Pyroscope
2
- VERSION = "0.1.1".freeze
2
+ VERSION = '0.3.1'.freeze
3
3
  end
data/lib/pyroscope.rb CHANGED
@@ -1,60 +1,103 @@
1
- require "pyroscope/version"
2
- require "pyroscope_c"
1
+ require 'ffi'
3
2
 
4
3
  module Pyroscope
5
- Config = Struct.new(:app_name, :server_address, :auth_token, :sample_rate, :with_subprocesses, :log_level, :tags)
4
+ module Rust
5
+ extend FFI::Library
6
+ ffi_lib File.expand_path(File.dirname(__FILE__)) + "/rbspy/rbspy.#{RbConfig::CONFIG["DLEXT"]}"
7
+ attach_function :initialize_agent, [:string, :string, :string, :int, :bool, :bool, :bool, :bool, :string], :bool
8
+ attach_function :add_thread_tag, [:uint64, :string, :string], :bool
9
+ attach_function :remove_thread_tag, [:uint64, :string, :string], :bool
10
+ attach_function :add_global_tag, [:string, :string], :bool
11
+ attach_function :remove_global_tag, [:string, :string], :bool
12
+ attach_function :drop_agent, [], :bool
13
+ end
14
+
15
+ module Utils
16
+ extend FFI::Library
17
+ ffi_lib File.expand_path(File.dirname(__FILE__)) + "/thread_id/thread_id.#{RbConfig::CONFIG["DLEXT"]}"
18
+ attach_function :thread_id, [], :uint64
19
+ end
20
+
21
+ Config = Struct.new(:application_name, :app_name, :server_address, :auth_token, :sample_rate, :detect_subprocesses, :on_cpu, :report_pid, :report_thread_id, :log_level, :tags) do
22
+ def initialize(*)
23
+ self.application_name = ''
24
+ self.server_address = 'http://localhost:4040'
25
+ self.auth_token = ''
26
+ self.sample_rate = 100
27
+ self.detect_subprocesses = false
28
+ self.on_cpu = true
29
+ self.report_pid = false
30
+ self.report_thread_id = false
31
+ self.log_level = 'info'
32
+ self.tags = {}
33
+ super
34
+ end
35
+ end
6
36
 
7
37
  class << self
8
38
  def configure
9
- @configuration = Config.new
10
- yield @configuration
11
- _start(
12
- @configuration.app_name,
13
- @configuration.server_address,
14
- @configuration.auth_token || "",
15
- @configuration.sample_rate || 100,
16
- @configuration.with_subprocesses || 0,
17
- @configuration.log_level || "error",
18
- )
19
- tag(@configuration.tags) if @configuration.tags
20
- end
39
+ @config = Config.new
21
40
 
22
- def stop
23
- _stop
24
- end
41
+ # Pass config to the block
42
+ yield @config
25
43
 
26
- def change_name(new_name)
27
- _change_name(new_name)
44
+ Rust.initialize_agent(
45
+ @config.app_name || @config.application_name || "",
46
+ @config.server_address || "",
47
+ @config.auth_token || "",
48
+ @config.sample_rate || 100,
49
+ @config.detect_subprocesses || false,
50
+ @config.on_cpu || false,
51
+ @config.report_pid || false,
52
+ @config.report_thread_id || false,
53
+ tags_to_string(@config.tags || {})
54
+ )
28
55
  end
29
56
 
30
57
  def tag_wrapper(tags)
31
- tag(tags)
32
-
58
+ tid = thread_id
59
+ _add_tags(tid, tags)
33
60
  begin
34
61
  yield
35
62
  ensure
36
- remove_tags(*tags.keys)
63
+ _remove_tags(tid, tags)
37
64
  end
38
65
  end
39
66
 
40
67
  def tag(tags)
41
- tags.each_pair do |key, val|
42
- _set_tag(key.to_s, val.to_s)
43
- end
68
+ warn("deprecated. Use `Pyroscope.tag_wrapper` instead.")
44
69
  end
45
70
 
46
- def remove_tags(*keys)
47
- keys.each do |key|
48
- _set_tag(key.to_s, "")
71
+ def remove_tags(*tags)
72
+ warn("deprecated. Use `Pyroscope.tag_wrapper` instead.")
73
+ end
74
+
75
+ # convert tags object to string
76
+ def tags_to_string(tags)
77
+ tags.map { |k, v| "#{k}=#{v}" }.join(',')
78
+ end
79
+
80
+ # get thread id
81
+ def thread_id
82
+ return Utils.thread_id
83
+ end
84
+
85
+ # add tags
86
+ def _add_tags(thread_id, tags)
87
+ tags.each do |tag_name, tag_value|
88
+ Rust.add_thread_tag(thread_id, tag_name.to_s, tag_value.to_s)
49
89
  end
50
90
  end
51
91
 
52
- def test_logger
53
- _test_logger
92
+ # remove tags
93
+ def _remove_tags(thread_id, tags)
94
+ tags.each do |tag_name, tag_value|
95
+ Rust.remove_thread_tag(thread_id, tag_name.to_s, tag_value.to_s)
96
+ end
54
97
  end
55
98
 
56
- def build_summary
57
- _build_summary
99
+ def drop
100
+ Rust.drop_agent
58
101
  end
59
102
  end
60
103
  end
data/pyroscope.gemspec CHANGED
@@ -1,27 +1,32 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
- require 'pyroscope/version'
1
+ require_relative "lib/pyroscope/version"
5
2
 
6
3
  Gem::Specification.new do |s|
7
- s.name = "pyroscope"
8
- s.version = Pyroscope::VERSION
9
- s.summary = "pyroscope"
10
- s.description = "pyroscope client integration for ruby"
11
- s.authors = ["Pyroscope Team"]
12
- s.email = "contact@pyroscope.io"
13
- s.files = `git ls-files`.split("\n")
14
- s.files += Dir.glob("ext/**/**")
15
- # s.files << "lib/pyroscope_c.bundle"
16
- s.homepage = "http://rubygems.org/gems/pyroscope"
17
- s.license = "Apache-2.0"
18
- s.require_paths = ["lib"]
19
- s.require_paths << "ext/pyroscope"
20
- s.extensions << "ext/pyroscope/extconf.rb"
4
+ s.name = 'pyroscope'
5
+ s.version = Pyroscope::VERSION
6
+ s.summary = 'Pyroscope'
7
+ s.description = 'Pyroscope FFI Integration for Ruby'
8
+ s.authors = ['Pyroscope Team']
9
+ s.email = ['contact@pyroscope.io']
10
+ s.homepage = 'https://pyroscope.io'
11
+ s.license = 'Apache-2.0'
12
+
13
+ # Specify which files should be added to the gem when it is released.
14
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
15
+ #s.files = Dir.chdir(__dir__) do
16
+ #`git ls-files -z`.split("\x0").reject do |f|
17
+ #(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
18
+ #end
19
+ #end
20
+ s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(\.|G|spec|Rakefile)/ }
21
+
22
+ s.platform = Gem::Platform::RUBY
23
+
24
+ s.required_ruby_version = ">= 2.5.9"
25
+
26
+ s.extensions = ['ext/rbspy/extconf.rb', 'ext/thread_id/extconf.rb']
27
+
28
+ s.add_dependency 'ffi'
21
29
 
22
- s.add_development_dependency "bundler"
23
- s.add_development_dependency "rake"
24
- s.add_development_dependency "rake-compiler"
25
- s.add_development_dependency "rubygems-tasks"
26
- s.add_development_dependency "rspec"
30
+ s.add_development_dependency 'bundler'
31
+ s.add_development_dependency 'rake', '~> 13.0'
27
32
  end
data/scripts/docker.sh ADDED
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ set -ex
3
+
4
+ BUILD_DIR="/work"
5
+
6
+ docker run \
7
+ -w /work/pyroscope_ffi/ruby/elflib/rbspy \
8
+ -v `pwd`:/work \
9
+ quay.io/pypa/${BUILD_ARCH} \
10
+ sh manylinux.sh
11
+
12
+ docker run \
13
+ -w /work/pyroscope_ffi/ruby/elflib/thread_id \
14
+ -v `pwd`:/work \
15
+ quay.io/pypa/${BUILD_ARCH} \
16
+ sh manylinux.sh