class Args
Platform-specific clang configuration: finding libclang, locating the resource directory, and injecting extra command-line arguments into parse_translation_unit.
All discovery is lazy — nothing runs until a method is called.
Definitions
attr_writer :libclang_loaded_path
Set the loaded libclang path after ffi_lib succeeds, so resource dir probing can use it.
Signature
-
parameter
pathString | Nil Path to the loaded libclang library.
def self.create
Factory: returns the platform-appropriate subclass instance.
Signature
-
returns
Args A platform-specific instance.
Implementation
def self.create
case FFI::Clang.platform
when :darwin
DarwinArgs.new
when :mingw
MingwArgs.new
when :mswin
MswinArgs.new
else
LinuxArgs.new
end
end
def libclang_paths
Ordered list of library paths for ffi_lib.
Signature
-
returns
Array(String) Paths to try when loading libclang.
Implementation
def libclang_paths
@libclang_paths ||= if ENV["LIBCLANG"]
[ENV["LIBCLANG"]]
else
find_libclang_paths
end
end
def command_line_args(command_line_args = [])
Extra args to inject into parse_translation_unit. Includes -resource-dir (unless already present) plus any platform-specific flags.
Signature
-
parameter
command_line_argsArray(String) The existing command line arguments.
-
returns
Array(String) Additional args to append.
Implementation
def command_line_args(command_line_args = [])
args = []
if !command_line_args.include?("-resource-dir") && resource_dir
args.push("-resource-dir", resource_dir)
end
args.concat(extra_args(command_line_args))
args
end
def resource_dir
The resolved resource directory path.
Signature
-
returns
String | Nil The resource directory path, or nil if not found.
Implementation
def resource_dir
if defined?(@resource_dir)
@resource_dir
else
@resource_dir = find_resource_dir
end
end
def post_load(library)
Called after ffi_lib successfully loads libclang. Subclasses may override to perform post-load setup.
Signature
-
parameter
libraryFFI::DynamicLibrary The loaded libclang library.
Implementation
def post_load(library)
end
def extra_args(command_line_args)
Platform-specific extra args beyond -resource-dir. Subclasses override as needed.
Signature
-
parameter
command_line_argsArray(String) The existing command line arguments.
-
returns
Array(String) Additional platform-specific args.
Implementation
def extra_args(command_line_args)
[]
end
def llvm_config
Find the llvm-config binary. Checks LLVM_CONFIG env, then PATH (unless LLVM_VERSION is set to pin a specific version).
Signature
-
returns
String | Nil Path to llvm-config, or nil.
Implementation
def llvm_config
if defined?(@llvm_config)
return @llvm_config
end
@llvm_config = ENV["LLVM_CONFIG"]
unless @llvm_config || ENV["LLVM_VERSION"]
@llvm_config = "llvm-config"
end
@llvm_config
end
def llvm_library_dir
Query llvm-config for its library directory.
Signature
-
returns
String | Nil The library directory, or nil.
Implementation
def llvm_library_dir
return nil unless llvm_config
@llvm_library_dir ||= run_command(llvm_config, "--libdir")
end
def llvm_bin_dir
Query llvm-config for its binary directory.
Signature
-
returns
String | Nil The binary directory, or nil.
Implementation
def llvm_bin_dir
return nil unless llvm_config
@llvm_bin_dir ||= run_command(llvm_config, "--bindir")
end
def resource_dir_from_clang(clang)
Ask a clang binary for its resource directory.
Signature
-
parameter
clangString Path to or name of the clang binary.
-
returns
String | Nil The resource directory path, or nil.
Implementation
def resource_dir_from_clang(clang)
dir = run_command(clang, "-print-resource-dir")
valid_resource_dir?(dir) ? dir : nil
end
def probe_from_libclang(libclang_path)
Probe for the resource directory relative to the libclang shared library.
Signature
-
parameter
libclang_pathString Path to the libclang shared library.
-
returns
String | Nil The resource directory path, or nil.
Implementation
def probe_from_libclang(libclang_path)
base = ::File.expand_path(::File.dirname(libclang_path))
candidates = []
candidates.concat Dir.glob(::File.join(base, "..", "lib", "clang", "*"))
candidates.concat Dir.glob(::File.join(base, "..", "..", "lib", "clang", "*"))
candidates.concat Dir.glob(::File.join(base, "clang", "*"))
candidates = candidates.map{|p| ::File.expand_path(p)}.uniq
candidates
.select{|dir| valid_resource_dir?(dir)}
.sort
.last
end
def valid_resource_dir?(dir)
Check whether a directory looks like a valid clang resource directory.
Signature
-
parameter
dirString | Nil The directory to check.
-
returns
Boolean True if the directory contains expected compiler headers.
Implementation
def valid_resource_dir?(dir)
return false unless dir && ::File.directory?(dir)
inc = ::File.join(dir, "include")
return false unless ::File.directory?(inc)
::File.exist?(::File.join(inc, "stddef.h")) ||
::File.exist?(::File.join(inc, "__stddef_size_t.h")) ||
::File.exist?(::File.join(inc, "stdint.h"))
end
def find_resource_dir
Common resource dir search: env override, clang from llvm-config, clang on PATH, probe from loaded libclang.
Signature
-
returns
String | Nil The resource directory path, or nil.
Implementation
def find_resource_dir
# 1. Explicit override via environment variable.
env = ENV["LIBCLANG_RESOURCE_DIR"]
return env if valid_resource_dir?(env)
# 2. Clang binary from llvm-config.
if (bin_dir = llvm_bin_dir)
clang_path = ::File.join(bin_dir, "clang")
if (dir = resource_dir_from_clang(clang_path))
return dir
end
end
# 3. clang on PATH.
if (dir = resource_dir_from_clang("clang"))
return dir
end
# 4. Probe relative to the loaded libclang shared library.
if @libclang_loaded_path && (dir = probe_from_libclang(@libclang_loaded_path))
return dir
end
nil
end