Class: Kompo::FindNativeExtensions
- Inherits:
-
Taski::Task
- Object
- Taski::Task
- Kompo::FindNativeExtensions
- Defined in:
- lib/kompo/tasks/find_native_extensions.rb
Overview
Find native gem extensions that need to be built Exports:
- extensions: Array of hashes with extension info (dir_name, gem_ext_name, is_rust)
Instance Method Summary collapse
Instance Method Details
#run ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/kompo/tasks/find_native_extensions.rb', line 12 def run @extensions = [] ruby_version = InstallRuby.ruby_version ruby_build_path = InstallRuby.ruby_build_path ruby_install_dir = InstallRuby.ruby_install_dir # Get Init functions already defined in libruby-static builtin_init_funcs = get_builtin_init_functions(ruby_install_dir) # Find bundled gems with native extensions (Ruby 4.0+) # Skip if --no-stdlib is specified (bundled gems are part of stdlib) no_stdlib = Taski.args.fetch(:no_stdlib, false) unless no_stdlib bundled_gems_dir = File.join(ruby_build_path, "ruby-#{ruby_version}", ".bundle", "gems") find_bundled_gem_extensions(bundled_gems_dir, builtin_init_funcs) end # Skip user gems if no Gemfile unless CopyGemfile.gemfile_exists puts "No Gemfile, skipping user gem native extensions" puts "Found #{@extensions.size} native extensions to build" return end bundle_ruby_dir = BundleInstall.bundle_ruby_dir # Find all native extensions in installed gems extconf_files = Dir.glob(File.join(bundle_ruby_dir, "gems/**/extconf.rb")) extconf_files.each do |extconf_path| dir_name = File.dirname(extconf_path) gem_ext_name = File.basename(dir_name) # Skip if Init function is already defined in libruby-static # This catches gems like prism that are compiled into Ruby core init_func = "Init_#{gem_ext_name}" if builtin_init_funcs.include?(init_func) puts "skip: #{gem_ext_name} is already built into Ruby (#{init_func} found in libruby-static)" next end # Skip if this extension is part of Ruby standard library ruby_std_lib = dir_name.split("/").drop_while { |p| p != "ext" }.join("/") ruby_ext_objects = Dir.glob(File.join(ruby_build_path, "ruby-#{ruby_version}", "ext", "**", "*.o")) if ruby_ext_objects.any? { |o| o.include?(ruby_std_lib) } puts "skip: #{gem_ext_name} is included in Ruby standard library" next end # Check if already added (e.g., as bundled gem) # Prefer Gemfile versions over prebuilt bundled gems existing = @extensions.find { |e| e[:gem_ext_name] == gem_ext_name } if existing if existing[:is_prebuilt] # Replace prebuilt bundled gem with Gemfile version puts "replacing: #{gem_ext_name} prebuilt bundled gem with Gemfile version" @extensions.delete(existing) else # Already added as non-prebuilt, skip puts "skip: #{gem_ext_name} is already added" next end end cargo_toml = File.join(dir_name, "Cargo.toml") is_rust = File.exist?(cargo_toml) @extensions << { dir_name: dir_name, gem_ext_name: gem_ext_name, is_rust: is_rust, cargo_toml: is_rust ? cargo_toml : nil, is_prebuilt: false } end puts "Found #{@extensions.size} native extensions to build" end |