diff --git a/Gemfile.lock b/Gemfile.lock index c5a848c..a4edcb9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,6 +2,7 @@ PATH remote: . specs: easy_compile (0.1.1) + prism rake-compiler thor @@ -9,6 +10,7 @@ GEM remote: https://rubygems.org/ specs: minitest (5.25.5) + prism (1.6.0) rake (13.3.0) rake-compiler (1.3.0) rake diff --git a/easy_compile.gemspec b/easy_compile.gemspec index 800b57f..4bc5a28 100644 --- a/easy_compile.gemspec +++ b/easy_compile.gemspec @@ -25,4 +25,5 @@ Gem::Specification.new do |spec| spec.add_dependency "rake-compiler" spec.add_dependency "thor" + spec.add_dependency "prism" end diff --git a/lib/easy_compile/cli.rb b/lib/easy_compile/cli.rb index e5dec7b..d68324b 100644 --- a/lib/easy_compile/cli.rb +++ b/lib/easy_compile/cli.rb @@ -134,7 +134,8 @@ def run_rake_tasks!(*tasks) rake_specs = Gem.loaded_specs["rake"] rake_executable = rake_specs.bin_file("rake") rake_path = rake_specs.full_require_paths - load_paths = (rake_compiler_path + rake_path).join(File::PATH_SEPARATOR) + prism_path = Gem.loaded_specs["prism"].full_require_paths + load_paths = (rake_compiler_path + rake_path + prism_path).join(File::PATH_SEPARATOR) system({ "RUBYLIB" => load_paths }, "bundle exec #{RbConfig.ruby} #{rake_executable} #{all_tasks} -R#{rakelibdir}", exception: true) end diff --git a/lib/easy_compile/compilation_tasks.rb b/lib/easy_compile/compilation_tasks.rb index 79be278..ff10471 100644 --- a/lib/easy_compile/compilation_tasks.rb +++ b/lib/easy_compile/compilation_tasks.rb @@ -3,11 +3,11 @@ require "bundler" require "rubygems/package_task" require "rake/extensiontask" +require_relative "create_makefile_finder" module EasyCompile class CompilationTasks attr_reader :gemspec, :native, :create_packaging_task, :extension_task - attr_accessor :binary_name def initialize(create_packaging_task = false, gemspec = nil) @gemspec = Bundler.load_gemspec(gemspec || find_gemspec) @@ -17,10 +17,9 @@ def initialize(create_packaging_task = false, gemspec = nil) end def setup - with_mkmf_monkey_patch do - gemspec.extensions.each do |path| - define_task(path) - end + gemspec.extensions.each do |path| + binary_name = parse_extconf(path) + define_task(path, binary_name) end setup_packaging if create_packaging_task @@ -52,46 +51,21 @@ def setup_packaging end end - def with_mkmf_monkey_patch - require "mkmf" - - instance = self - - previous_create_makefile = method(:create_makefile) - Object.define_method(:create_makefile) do |name, *args| - instance.binary_name = name - previous_create_makefile.call(name, *args) - end - - Object.define_method(:create_rust_makefile) do |name, *args| - instance.binary_name = name - end - - yield - ensure - Object.remove_method(:create_makefile) - Object.remove_method(:create_rust_makefile) - end - - def define_task(path) - require File.expand_path(path) - + def define_task(path, binary_name) @extension_task = Rake::ExtensionTask.new do |ext| ext.name = File.basename(binary_name) ext.config_script = File.basename(path) ext.ext_dir = File.dirname(path) - ext.lib_dir = binary_lib_dir if binary_lib_dir + ext.lib_dir = binary_lib_dir(binary_name) if binary_lib_dir(binary_name) ext.gem_spec = gemspec ext.cross_platform = normalized_platform ext.cross_compile = true end disable_shared unless Gem.win_platform? - ensure - self.binary_name = nil end - def binary_lib_dir + def binary_lib_dir(binary_name) dir = File.dirname(binary_name) return if dir == "." @@ -137,5 +111,12 @@ def verify_gemspec! This tool can't be used on pure Ruby gems. EOM end + + def parse_extconf(path) + visitor = CreateMakefileFinder.new + Prism.parse_file(path).value.accept(visitor) + + visitor.binary_name + end end end diff --git a/lib/easy_compile/create_makefile_finder.rb b/lib/easy_compile/create_makefile_finder.rb new file mode 100644 index 0000000..99bbefd --- /dev/null +++ b/lib/easy_compile/create_makefile_finder.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "prism" + +module EasyCompile + class CreateMakefileFinder < Prism::Visitor + attr_reader :binary_name + + def visit_call_node(node) + super + looking_for = [:create_makefile, :create_rust_makefile] + return unless looking_for.include?(node.name) + + @binary_name = node.arguments.child_nodes.first.content + end + end +end