gem.rb: detect external HAL by hal-<short>-* naming

67f137e201 introduced spec.hal_pattern on the target gem to
declare its expected HAL provider names.  But the decision to
override is naturally an opt-in choice belonging to the external
HAL gem (or build_config), not the target.  Drop hal_pattern and
hardcode the naming rule in resolve_external_hal!: a gem named
`hal-<short>-<conf>` overrides the gem whose last `-`-separated
segment is <short>.  No spec attribute on the target gem; no flag
on add_dependency; the convention does all the work.

The pre-be6413f0d8 convention was `hal-<platform>-<gem>` (e.g.,
hal-posix-task) for platform sort across gems.  Now that the
common platforms live under ports/, sorting by which target gem
a HAL is for is more useful, so the order is reversed:
`hal-<gem>-<conf>` (e.g., hal-task-glib).

ref #6825

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-17 18:38:38 +09:00
parent 67f137e201
commit e7f5387f5d
2 changed files with 12 additions and 16 deletions
+12 -12
View File
@@ -26,7 +26,6 @@ module MRuby
attr_accessor :rbfiles, :objs
attr_reader :port_objs
attr_accessor :hal_pattern
attr_writer :test_objs, :test_rbfiles
attr_accessor :test_args, :test_preload
@@ -67,7 +66,7 @@ module MRuby
# chain: later names act as defaults for gems that don't ship
# a port for the earlier names. These objs are tracked
# separately so List#resolve_external_hal! can drop them when
# an external HAL provider matching spec.hal_pattern is loaded.
# an external HAL provider (gem named hal-<short>-*) is loaded.
@port_objs = []
build.effective_ports.each do |port|
port_dir = "#{@dir}/ports/#{port}"
@@ -466,22 +465,23 @@ module MRuby
resolve_external_hal!
end
# If a gem declares `spec.hal_pattern = /regex/`, any other gem
# whose name matches the regex is treated as the external HAL
# provider for that gem -- the target gem's ports/* sources are
# dropped from its object list (the matching gem itself supplies
# the implementation). Two or more matches is a build error.
# A gem named `hal-<short>-<conf>` is treated as the external
# HAL provider for the gem whose name's last `-`-separated
# segment is <short> (e.g., hal-task-glib provides the HAL for
# mruby-task). The target gem's ports/* sources are dropped
# from its object list -- the matching gem supplies the
# implementation. Two or more matches is a build error.
def resolve_external_hal!
each do |target|
next unless target.hal_pattern
overriders = select { |g| g != target && g.name =~ target.hal_pattern }
next if target.port_objs.nil? || target.port_objs.empty?
short = target.name.split('-').last
pattern = /\Ahal-#{Regexp.escape(short)}-.+\z/
overriders = select { |g| g != target && g.name =~ pattern }
next if overriders.empty?
if overriders.size > 1
fail "Multiple gems match #{target.hal_pattern.inspect} as " \
"HAL provider for '#{target.name}': " +
fail "Multiple HAL providers for '#{target.name}': " +
overriders.map(&:name).join(", ")
end
next if target.port_objs.nil? || target.port_objs.empty?
target.objs.reject! { |o| target.port_objs.include?(o) }
end
end
-4
View File
@@ -6,10 +6,6 @@ MRuby::Gem::Specification.new('mruby-task') do |spec|
# Enable task scheduler globally (required for vm.c integration)
spec.build.defines << 'MRB_USE_TASK_SCHEDULER'
# A gem named hal-<name>-task (declaring add_dependency 'mruby-task')
# replaces the built-in ports/<conf.ports>/ HAL implementation.
spec.hal_pattern = /\Ahal-.*-task\z/
if spec.for_windows?
spec.linker.libraries << "winmm"
end