mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
gem.rb: hal_pattern for external HAL provider override
A gem can declare
spec.hal_pattern = /\Ahal-.*-task\z/
to indicate that another gem whose name matches the pattern (and
which depends on this gem for headers) replaces the built-in
ports/<conf.ports>/ HAL implementation. After all gems are set
up, List#resolve_external_hal! drops the target's ports/* objs
from its object list so the matching gem supplies the HAL
symbols. Two or more matches is reported as a build error.
This restores the pre-be6413f0d8 ability to maintain an
out-of-tree HAL via add_dependency + naming convention, without
reintroducing the "HAL information scattered across gems"
problem: the parent gem still owns the scheduler, headers, and
bundled posix/win ports; external HAL gems are an explicit,
opt-in override.
Declare /\Ahal-.*-task\z/ for mruby-task -- the same naming
pattern used before be6413f0d8.
ref #6825
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+29
-2
@@ -25,6 +25,8 @@ module MRuby
|
|||||||
alias :author= :authors=
|
alias :author= :authors=
|
||||||
|
|
||||||
attr_accessor :rbfiles, :objs
|
attr_accessor :rbfiles, :objs
|
||||||
|
attr_reader :port_objs
|
||||||
|
attr_accessor :hal_pattern
|
||||||
attr_writer :test_objs, :test_rbfiles
|
attr_writer :test_objs, :test_rbfiles
|
||||||
attr_accessor :test_args, :test_preload
|
attr_accessor :test_args, :test_preload
|
||||||
|
|
||||||
@@ -63,11 +65,15 @@ module MRuby
|
|||||||
# Add platform-specific sources from the first matching
|
# Add platform-specific sources from the first matching
|
||||||
# ports/<name>/ directory. effective_ports is a fallback
|
# ports/<name>/ directory. effective_ports is a fallback
|
||||||
# chain: later names act as defaults for gems that don't ship
|
# chain: later names act as defaults for gems that don't ship
|
||||||
# a port for the earlier names.
|
# 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.
|
||||||
|
@port_objs = []
|
||||||
build.effective_ports.each do |port|
|
build.effective_ports.each do |port|
|
||||||
port_dir = "#{@dir}/ports/#{port}"
|
port_dir = "#{@dir}/ports/#{port}"
|
||||||
if File.directory?(port_dir)
|
if File.directory?(port_dir)
|
||||||
@objs += srcs_to_objs("ports/#{port}")
|
@port_objs = srcs_to_objs("ports/#{port}")
|
||||||
|
@objs += @port_objs
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -457,6 +463,27 @@ module MRuby
|
|||||||
self.each(&:setup)
|
self.each(&:setup)
|
||||||
gemset = self.setup_dependencies(build).keys.sort
|
gemset = self.setup_dependencies(build).keys.sort
|
||||||
end until gemset == gemset_prev
|
end until gemset == gemset_prev
|
||||||
|
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.
|
||||||
|
def resolve_external_hal!
|
||||||
|
each do |target|
|
||||||
|
next unless target.hal_pattern
|
||||||
|
overriders = select { |g| g != target && g.name =~ target.hal_pattern }
|
||||||
|
next if overriders.empty?
|
||||||
|
if overriders.size > 1
|
||||||
|
fail "Multiple gems match #{target.hal_pattern.inspect} as " \
|
||||||
|
"HAL provider 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
|
end
|
||||||
|
|
||||||
def setup_build
|
def setup_build
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ MRuby::Gem::Specification.new('mruby-task') do |spec|
|
|||||||
# Enable task scheduler globally (required for vm.c integration)
|
# Enable task scheduler globally (required for vm.c integration)
|
||||||
spec.build.defines << 'MRB_USE_TASK_SCHEDULER'
|
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?
|
if spec.for_windows?
|
||||||
spec.linker.libraries << "winmm"
|
spec.linker.libraries << "winmm"
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user