Class: MilkTea::RawBindings::Binding

Inherits:
Object
  • Object
show all
Defined in:
lib/milk_tea/bindings/raw_bindings.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, module_name:, binding_path:, header_candidates:, tracked_header_paths: [], tracked_header_prefixes: [], declaration_name_prefixes: [], excluded_declaration_names: [], include_directives: nil, bindgen_defines: [], bindgen_include_directives: [], module_imports: [], link_libraries: [], link_flags: [], env_var: nil, clang: nil, clang_args: [], compiler_flags: [], implementation_defines: [], type_name_overrides: {}, type_overrides: {}, function_param_type_overrides: {}, function_return_type_overrides: {}, field_type_overrides: {}, vendored_library: nil, prepare: nil, generator: nil, allow_static_inline_functions: false, strip_leading_underscores: false) ⇒ Binding

Returns a new instance of Binding.



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
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 12

def initialize(name:, module_name:, binding_path:, header_candidates:, tracked_header_paths: [], tracked_header_prefixes: [], declaration_name_prefixes: [], excluded_declaration_names: [], include_directives: nil, bindgen_defines: [], bindgen_include_directives: [], module_imports: [], link_libraries: [], link_flags: [], env_var: nil, clang: nil, clang_args: [], compiler_flags: [], implementation_defines: [], type_name_overrides: {}, type_overrides: {}, function_param_type_overrides: {}, function_return_type_overrides: {}, field_type_overrides: {}, vendored_library: nil, prepare: nil, generator: nil, allow_static_inline_functions: false, strip_leading_underscores: false)
  @name = name.to_s
  @module_name = module_name
  @binding_path = File.expand_path(binding_path.to_s)
  @header_candidates = header_candidates.map { |path| File.expand_path(path) }.freeze
  @tracked_header_paths = tracked_header_paths.map { |path| File.expand_path(path) }.freeze
  @tracked_header_prefixes = tracked_header_prefixes.map { |path| File.expand_path(path) }.freeze
  @declaration_name_prefixes = declaration_name_prefixes.dup.freeze
  @excluded_declaration_names = excluded_declaration_names.map(&:to_s).freeze
  @include_directives = include_directives&.dup&.freeze
  @bindgen_defines = bindgen_defines.dup.freeze
  @bindgen_include_directives = bindgen_include_directives.dup.freeze
  @link_libraries = link_libraries.dup.freeze
  @link_flags = link_flags.dup.freeze
  @env_var = env_var
  @clang = clang
  @clang_args = clang_args.dup.freeze
  @compiler_flags = compiler_flags.dup.freeze
  @implementation_defines = implementation_defines.dup.freeze
  @module_imports = module_imports.dup.freeze
  @type_name_overrides = type_name_overrides.transform_keys(&:to_s).transform_values(&:to_s).freeze
  @type_overrides = type_overrides.transform_keys(&:to_s).freeze
  @function_param_type_overrides = normalize_function_param_type_overrides(function_param_type_overrides)
  @function_return_type_overrides = function_return_type_overrides.transform_keys(&:to_s).freeze
  @field_type_overrides = normalize_field_type_overrides(field_type_overrides)
  @vendored_library = vendored_library
  @prepare = prepare
  @generator = generator
  @allow_static_inline_functions = allow_static_inline_functions
  @strip_leading_underscores = strip_leading_underscores
end

Instance Attribute Details

#bindgen_definesObject (readonly)

Returns the value of attribute bindgen_defines.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def bindgen_defines
  @bindgen_defines
end

#bindgen_include_directivesObject (readonly)

Returns the value of attribute bindgen_include_directives.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def bindgen_include_directives
  @bindgen_include_directives
end

#binding_pathObject (readonly)

Returns the value of attribute binding_path.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def binding_path
  @binding_path
end

#clang_argsObject (readonly)

Returns the value of attribute clang_args.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def clang_args
  @clang_args
end

#compiler_flagsObject (readonly)

Returns the value of attribute compiler_flags.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def compiler_flags
  @compiler_flags
end

#declaration_name_prefixesObject (readonly)

Returns the value of attribute declaration_name_prefixes.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def declaration_name_prefixes
  @declaration_name_prefixes
end

#env_varObject (readonly)

Returns the value of attribute env_var.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def env_var
  @env_var
end

#excluded_declaration_namesObject (readonly)

Returns the value of attribute excluded_declaration_names.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def excluded_declaration_names
  @excluded_declaration_names
end

#field_type_overridesObject (readonly)

Returns the value of attribute field_type_overrides.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def field_type_overrides
  @field_type_overrides
end

#function_param_type_overridesObject (readonly)

Returns the value of attribute function_param_type_overrides.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def function_param_type_overrides
  @function_param_type_overrides
end

#function_return_type_overridesObject (readonly)

Returns the value of attribute function_return_type_overrides.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def function_return_type_overrides
  @function_return_type_overrides
end

#header_candidatesObject (readonly)

Returns the value of attribute header_candidates.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def header_candidates
  @header_candidates
end

#implementation_definesObject (readonly)

Returns the value of attribute implementation_defines.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def implementation_defines
  @implementation_defines
end

#include_directivesObject (readonly)

Returns the value of attribute include_directives.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def include_directives
  @include_directives
end

Returns the value of attribute link_libraries.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def link_libraries
  @link_libraries
end

#module_importsObject (readonly)

Returns the value of attribute module_imports.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def module_imports
  @module_imports
end

#module_nameObject (readonly)

Returns the value of attribute module_name.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def module_name
  @module_name
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def name
  @name
end

#strip_leading_underscoresObject (readonly)

Returns the value of attribute strip_leading_underscores.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def strip_leading_underscores
  @strip_leading_underscores
end

#tracked_header_pathsObject (readonly)

Returns the value of attribute tracked_header_paths.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def tracked_header_paths
  @tracked_header_paths
end

#tracked_header_prefixesObject (readonly)

Returns the value of attribute tracked_header_prefixes.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def tracked_header_prefixes
  @tracked_header_prefixes
end

#type_name_overridesObject (readonly)

Returns the value of attribute type_name_overrides.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def type_name_overrides
  @type_name_overrides
end

#type_overridesObject (readonly)

Returns the value of attribute type_overrides.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def type_overrides
  @type_overrides
end

#vendored_libraryObject (readonly)

Returns the value of attribute vendored_library.



10
11
12
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 10

def vendored_library
  @vendored_library
end

Instance Method Details

#build_flags(env: ENV, header_path: nil, platform: nil) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 116

def build_flags(env: ENV, header_path: nil, platform: nil)
  resolved_header_path = header_path || self.header_path(env:)
  include_dir = File.dirname(resolved_header_path)
  flags = []
  flags << "-I#{include_dir}" unless include_dir.nil? || include_dir.empty?
  implementation_defines.each do |define|
    flags << "-D#{define}"
  end
  flags.concat(compiler_flags)
  flags.concat(vendored_library.build_flags(platform:)) if vendored_library&.respond_to?(:build_flags)
  flags.uniq
end

#check!(env: ENV) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 136

def check!(env: ENV)
  prepare!(env:, cc: env.fetch("CC", "cc"))
  resolved_header_path = header_path(env:)
  expected = normalized_output(File.read(binding_path))
  actual = normalized_output(generate(env:, header_path: resolved_header_path))

  if expected != actual
    raise Error, <<~MESSAGE
      #{binding_path} is out of date for #{resolved_header_path}
      Run `rake #{task_name}` to regenerate it.
    MESSAGE
  end

  MilkTea::ModuleLoader.check_file(binding_path)
  resolved_header_path
end

#check_task_nameObject



48
49
50
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 48

def check_task_name
  "bindgen:check:#{name}"
end

#generate(env: ENV, header_path: nil) ⇒ Object



86
87
88
89
90
91
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 86

def generate(env: ENV, header_path: nil)
  resolved_header_path = header_path || self.header_path(env:)
  return @generator.call(self, env:, header_path: resolved_header_path) if @generator

  MilkTea::Bindgen.generate(**bindgen_kwargs(env:, header_path: resolved_header_path))
end

#header_labelObject



56
57
58
59
60
61
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 56

def header_label
  return include_directives.first if include_directives && !include_directives.empty?
  return File.basename(header_candidates.first) unless header_candidates.empty?

  name
end

#header_path(env: ENV) ⇒ Object

Raises:



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 70

def header_path(env: ENV)
  candidates = []
  override = env_var && env[env_var]
  candidates << override unless override.nil? || override.empty?
  candidates.concat(header_candidates)

  resolved = candidates.find { |path| File.file?(path) }
  return resolved if resolved

  if env_var
    raise Error, "#{header_label} header not found; set #{env_var} or install #{header_label} headers"
  end

  raise Error, "#{header_label} header not found"
end

#legacy_check_task_nameObject



52
53
54
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 52

def legacy_check_task_name
  "bindgen:check_#{name}"
end


63
64
65
66
67
68
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 63

def link_flags(platform: nil)
  flags = []
  flags.concat(vendored_library.link_flags(platform:)) if vendored_library
  flags.concat(@link_flags)
  flags.uniq
end

#nullable_policy_report(env: ENV, header_path: nil) ⇒ Object

Raises:



93
94
95
96
97
98
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 93

def nullable_policy_report(env: ENV, header_path: nil)
  resolved_header_path = header_path || self.header_path(env:)
  raise Error, "nullable policy report unavailable for custom raw binding generator #{name}" if @generator

  MilkTea::Bindgen.generate_with_report(**bindgen_kwargs(env:, header_path: resolved_header_path)).fetch(:nullable_policy_report)
end

#nullable_policy_report_path(root: MilkTea.root) ⇒ Object



100
101
102
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 100

def nullable_policy_report_path(root: MilkTea.root)
  File.expand_path(File.join(root, "tmp", "bindgen-nullable-reports", "#{name}.json"))
end

#prepare!(env: ENV, cc: ENV.fetch("CC", "cc"), platform: nil) ⇒ Object



153
154
155
156
157
158
159
160
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 153

def prepare!(env: ENV, cc: ENV.fetch("CC", "cc"), platform: nil)
  if @prepare
    kwargs = { env:, cc: }
    kwargs[:platform] = platform if prepare_accepts_keyword?(:platform)
    @prepare.call(self, **kwargs)
  end
  vendored_library&.prepare!(env:, cc:, platform:)
end

#task_nameObject



44
45
46
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 44

def task_name
  "bindgen:#{name}"
end

#write!(env: ENV) ⇒ Object



129
130
131
132
133
134
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 129

def write!(env: ENV)
  prepare!(env:, cc: env.fetch("CC", "cc"))
  resolved_header_path = header_path(env:)
  File.write(binding_path, generate(env:, header_path: resolved_header_path))
  resolved_header_path
end

#write_nullable_policy_report!(env: ENV, header_path: nil, output_path: nil) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/milk_tea/bindings/raw_bindings.rb', line 104

def write_nullable_policy_report!(env: ENV, header_path: nil, output_path: nil)
  resolved_header_path = header_path || self.header_path(env:)
  report_path = File.expand_path(output_path || nullable_policy_report_path)
  FileUtils.mkdir_p(File.dirname(report_path))
  if @generator
    File.write(report_path, JSON.pretty_generate({}))
  else
    File.write(report_path, JSON.pretty_generate(nullable_policy_report(env:, header_path: resolved_header_path)))
  end
  report_path
end