Skip to content

Commit 438e1f8

Browse files
committed
refactor: move executable logic into gem binaries
1 parent 59cda2b commit 438e1f8

File tree

7 files changed

+141
-136
lines changed

7 files changed

+141
-136
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ recorder.flush_trace(Dir.pwd)
3636
you can currently use it directly with
3737

3838
```bash
39-
ruby gems/codetracer-pure-ruby-recorder/lib/trace.rb [--out-dir DIR] <path to ruby file>
39+
ruby gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder [--out-dir DIR] <path to ruby file>
4040
# produces several trace json files in DIR,
4141
# or in `$CODETRACER_RUBY_RECORDER_OUT_DIR` if DIR is not provided.
4242
# Defaults to the current directory.
@@ -47,7 +47,7 @@ You can also invoke a lightweight CLI that loads the native tracer extension
4747
directly:
4848

4949
```bash
50-
ruby gems/codetracer-ruby-recorder/lib/native_trace.rb [--out-dir DIR] <path to ruby file>
50+
ruby gems/codetracer-ruby-recorder/bin/codetracer-ruby-recorder [--out-dir DIR] <path to ruby file>
5151
# Uses DIR or `$CODETRACER_RUBY_RECORDER_OUT_DIR` to choose where traces are saved.
5252
```
5353

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,52 @@
11
#!/usr/bin/env ruby
2-
require 'rbconfig'
3-
script = File.expand_path('../lib/trace.rb', __dir__)
4-
exec RbConfig.ruby, script, *ARGV
2+
# SPDX-License-Identifier: MIT
3+
# CLI for the pure Ruby tracer
4+
5+
require 'optparse'
6+
lib_dir = File.expand_path('../lib', __dir__)
7+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
8+
require 'codetracer_pure_ruby_recorder'
9+
10+
$tracer = Tracer.new($codetracer_record, debug: ENV['CODETRACER_RUBY_RECORDER_DEBUG'] == '1')
11+
CodetracerKernelPatches.install($tracer)
12+
13+
options = {}
14+
parser = OptionParser.new do |opts|
15+
opts.banner = "usage: codetracer-pure-ruby-recorder [options] <program> [args]"
16+
opts.on('-o DIR', '--out-dir DIR', 'Directory to write trace files') { |dir| options[:out_dir] = dir }
17+
opts.on('-h', '--help', 'Print this help') { puts opts; exit }
18+
end
19+
parser.order!
20+
21+
program = ARGV.shift
22+
if program.nil?
23+
$stderr.puts parser
24+
exit 1
25+
end
26+
27+
$tracer.record.register_call('', 1, '<top-level>', [])
28+
$tracer.ignore('lib/ruby')
29+
$tracer.ignore('trace.rb')
30+
$tracer.ignore('recorder.rb')
31+
$tracer.ignore('<internal:')
32+
$tracer.ignore('gems/')
33+
34+
$tracer.activate
35+
begin
36+
Kernel.load(program)
37+
rescue Exception => e
38+
if $tracer.debug
39+
old_puts ''
40+
old_puts '==== trace.rb error while tracing program ==='
41+
old_puts 'ERROR'
42+
old_puts e
43+
old_puts e.backtrace
44+
old_puts '====================='
45+
old_puts ''
46+
end
47+
end
48+
49+
$tracer.stop_tracing
50+
51+
out_dir = options[:out_dir] || ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] || Dir.pwd
52+
$tracer.record.serialize(program, out_dir)

gems/codetracer-pure-ruby-recorder/lib/trace.rb

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -255,53 +255,3 @@ def load_variables(binding)
255255
end
256256
end
257257

258-
if __FILE__ == $PROGRAM_NAME
259-
$tracer = Tracer.new($codetracer_record, debug: ENV['CODETRACER_RUBY_RECORDER_DEBUG'] == '1')
260-
CodetracerKernelPatches.install($tracer)
261-
262-
options = {}
263-
parser = OptionParser.new do |opts|
264-
opts.banner = "usage: ruby trace.rb [options] <program> [args]"
265-
opts.on('-o DIR', '--out-dir DIR', 'Directory to write trace files') do |dir|
266-
options[:out_dir] = dir
267-
end
268-
opts.on('-h', '--help', 'Print this help') do
269-
puts opts
270-
exit
271-
end
272-
end
273-
parser.order!
274-
275-
program = ARGV.shift
276-
if program.nil?
277-
$stderr.puts parser
278-
exit 1
279-
end
280-
281-
$tracer.record.register_call('', 1, '<top-level>', [])
282-
$tracer.ignore('lib/ruby')
283-
$tracer.ignore('trace.rb')
284-
$tracer.ignore('recorder.rb')
285-
$tracer.ignore('<internal:')
286-
$tracer.ignore('gems/')
287-
288-
$tracer.activate
289-
begin
290-
Kernel.load(program)
291-
rescue Exception => e
292-
if $tracer.debug
293-
old_puts ''
294-
old_puts '==== trace.rb error while tracing program ==='
295-
old_puts 'ERROR'
296-
old_puts e
297-
old_puts e.backtrace
298-
old_puts '====================='
299-
old_puts ''
300-
end
301-
end
302-
303-
$tracer.stop_tracing
304-
305-
out_dir = options[:out_dir] || ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] || Dir.pwd
306-
$tracer.record.serialize(program, out_dir)
307-
end
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/usr/bin/env ruby
2-
require 'rbconfig'
3-
script = File.expand_path('../lib/native_trace.rb', __dir__)
4-
exec RbConfig.ruby, script, *ARGV
2+
# SPDX-License-Identifier: MIT
3+
# CLI wrapper for the native tracer
54

5+
lib_dir = File.expand_path('../lib', __dir__)
6+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
7+
require 'native_trace'
8+
exit NativeTrace.execute(ARGV)
Lines changed: 77 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,99 @@
1-
#!/usr/bin/env ruby
21
# SPDX-License-Identifier: MIT
3-
# Simple utility loading the native tracer extension and executing a program.
2+
# Library providing a helper method to execute the native tracer.
43

54
require 'optparse'
65
require 'fileutils'
76
require 'rbconfig'
87

9-
options = {}
10-
parser = OptionParser.new do |opts|
11-
opts.banner = "usage: ruby native_trace.rb [options] <program> [args]"
12-
opts.on('-o DIR', '--out-dir DIR', 'Directory to write trace files') do |dir|
13-
options[:out_dir] = dir
14-
end
15-
opts.on('-h', '--help', 'Print this help') do
16-
puts opts
17-
exit
18-
end
19-
end
20-
parser.order!
8+
module NativeTrace
9+
# Execute the native tracer CLI logic with the provided +argv+.
10+
def self.execute(argv)
11+
options = {}
12+
parser = OptionParser.new do |opts|
13+
opts.banner = 'usage: codetracer-ruby-recorder [options] <program> [args]'
14+
opts.on('-o DIR', '--out-dir DIR', 'Directory to write trace files') do |dir|
15+
options[:out_dir] = dir
16+
end
17+
opts.on('-h', '--help', 'Print this help') do
18+
puts opts
19+
return 0
20+
end
21+
end
22+
parser.order!(argv)
2123

22-
if ARGV.empty?
23-
$stderr.puts parser
24-
exit 1
25-
end
24+
if argv.empty?
25+
$stderr.puts parser
26+
return 1
27+
end
2628

27-
out_dir = options[:out_dir] || ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] || Dir.pwd
28-
ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] = out_dir
29+
out_dir = options[:out_dir] || ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] || Dir.pwd
30+
ENV['CODETRACER_RUBY_RECORDER_OUT_DIR'] = out_dir
2931

30-
# Path to the compiled native extension
31-
ext_dir = File.expand_path('../ext/native_tracer/target/release', __dir__)
32-
dlext = RbConfig::CONFIG['DLEXT']
33-
target_path = File.join(ext_dir, "codetracer_ruby_recorder.#{dlext}")
34-
unless File.exist?(target_path)
35-
extensions = %w[so bundle dylib dll]
36-
alt_path = extensions
37-
.map { |ext| File.join(ext_dir, "libcodetracer_ruby_recorder.#{ext}") }
38-
.find { |path| File.exist?(path) }
39-
if alt_path
40-
begin
41-
File.symlink(alt_path, target_path)
42-
rescue StandardError
43-
FileUtils.cp(alt_path, target_path)
32+
ext_dir = File.expand_path('../ext/native_tracer/target/release', __dir__)
33+
dlext = RbConfig::CONFIG['DLEXT']
34+
target_path = File.join(ext_dir, "codetracer_ruby_recorder.#{dlext}")
35+
unless File.exist?(target_path)
36+
extensions = %w[so bundle dylib dll]
37+
alt_path = extensions
38+
.map { |ext| File.join(ext_dir, "libcodetracer_ruby_recorder.#{ext}") }
39+
.find { |path| File.exist?(path) }
40+
if alt_path
41+
begin
42+
File.symlink(alt_path, target_path)
43+
rescue StandardError
44+
FileUtils.cp(alt_path, target_path)
45+
end
46+
end
4447
end
45-
end
46-
end
4748

48-
recorder = nil
49-
begin
50-
require target_path
51-
recorder = RubyRecorder.new
52-
$recorder = recorder
49+
recorder = nil
50+
begin
51+
require target_path
52+
recorder = RubyRecorder.new
53+
$recorder = recorder
5354

54-
module Kernel
55-
alias :old_p :p
56-
alias :old_puts :puts
57-
alias :old_print :print
55+
Kernel.module_eval do
56+
alias :old_p :p
57+
alias :old_puts :puts
58+
alias :old_print :print
5859

59-
def p(*args)
60-
if $recorder
61-
loc = caller_locations(1,1).first
62-
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
63-
end
64-
old_p(*args)
65-
end
60+
define_method(:p) do |*args|
61+
if $recorder
62+
loc = caller_locations(1,1).first
63+
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
64+
end
65+
old_p(*args)
66+
end
6667

67-
def puts(*args)
68-
if $recorder
69-
loc = caller_locations(1,1).first
70-
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
68+
define_method(:puts) do |*args|
69+
if $recorder
70+
loc = caller_locations(1,1).first
71+
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
72+
end
73+
old_puts(*args)
74+
end
75+
76+
define_method(:print) do |*args|
77+
if $recorder
78+
loc = caller_locations(1,1).first
79+
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
80+
end
81+
old_print(*args)
82+
end
7183
end
72-
old_puts(*args)
84+
rescue Exception => e
85+
warn "native tracer unavailable: #{e}"
7386
end
7487

75-
def print(*args)
76-
if $recorder
77-
loc = caller_locations(1,1).first
78-
$recorder.record_event(loc.path, loc.lineno, args.join("\n"))
79-
end
80-
old_print(*args)
88+
program = argv.shift
89+
recorder.enable_tracing if recorder
90+
load program
91+
if recorder
92+
recorder.disable_tracing
93+
recorder.flush_trace(out_dir)
8194
end
95+
0
8296
end
83-
84-
rescue Exception => e
85-
warn "native tracer unavailable: #{e}"
8697
end
8798

88-
program = ARGV.shift
89-
recorder.enable_tracing if recorder
90-
load program
91-
if recorder
92-
recorder.disable_tracing
93-
recorder.flush_trace(out_dir)
94-
end
9599

test/benchmarks/run_benchmarks.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def run_benchmark(name)
5353
native_dir = File.join(TMP_DIR, name, 'native')
5454
FileUtils.mkdir_p(native_dir)
5555
elapsed = Benchmark.realtime do
56-
system(RbConfig.ruby, File.expand_path('../../gems/codetracer-ruby-recorder/lib/native_trace.rb', __dir__),
56+
system(RbConfig.ruby, File.expand_path('../../gems/codetracer-ruby-recorder/bin/codetracer-ruby-recorder', __dir__),
5757
'--out-dir', native_dir, program)
5858
raise 'Native trace failed' unless $?.success?
5959
end
@@ -64,7 +64,7 @@ def run_benchmark(name)
6464
pure_dir = File.join(TMP_DIR, name, 'pure')
6565
FileUtils.mkdir_p(pure_dir)
6666
elapsed = Benchmark.realtime do
67-
system(RbConfig.ruby, File.expand_path('../../gems/codetracer-pure-ruby-recorder/lib/trace.rb', __dir__),
67+
system(RbConfig.ruby, File.expand_path('../../gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder', __dir__),
6868
'--out-dir', pure_dir, program)
6969
raise 'Pure trace failed' unless $?.success?
7070
end

test/test_tracer.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ def program_args(base)
5151
Dir.glob(File.join(FIXTURE_DIR, '*_trace.json')).each do |fixture|
5252
base = File.basename(fixture, '_trace.json')
5353
define_method("test_#{base}") do
54-
pure_trace, pure_out = run_trace('gems/codetracer-pure-ruby-recorder/lib/trace.rb', "#{base}.rb", *program_args(base))
55-
native_trace, native_out = run_trace('gems/codetracer-ruby-recorder/lib/native_trace.rb', "#{base}.rb", *program_args(base))
54+
pure_trace, pure_out = run_trace('gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder', "#{base}.rb", *program_args(base))
55+
native_trace, native_out = run_trace('gems/codetracer-ruby-recorder/bin/codetracer-ruby-recorder', "#{base}.rb", *program_args(base))
5656

5757
expected = expected_trace("#{base}.rb")
5858
assert_equal expected, pure_trace
@@ -133,7 +133,7 @@ def test_pure_debug_smoke
133133
env = { 'CODETRACER_RUBY_RECORDER_DEBUG' => '1' }
134134
out_dir = File.join('test', 'tmp', 'debug_smoke')
135135
FileUtils.rm_rf(out_dir)
136-
stdout, stderr, status = Open3.capture3(env, RbConfig.ruby, 'gems/codetracer-pure-ruby-recorder/lib/trace.rb', '--out-dir', out_dir, File.join('test', 'programs', 'addition.rb'))
136+
stdout, stderr, status = Open3.capture3(env, RbConfig.ruby, 'gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder', '--out-dir', out_dir, File.join('test', 'programs', 'addition.rb'))
137137
raise "trace failed: #{stderr}" unless status.success?
138138

139139
lines = stdout.lines.map(&:chomp)

0 commit comments

Comments
 (0)