{"id":15724303,"url":"https://github.com/cedlemo/ruby-clangc","last_synced_at":"2025-03-13T00:31:26.204Z","repository":{"id":31705603,"uuid":"35271324","full_name":"cedlemo/ruby-clangc","owner":"cedlemo","description":"Ruby bindings for libclang","archived":false,"fork":false,"pushed_at":"2016-07-06T17:03:13.000Z","size":1462,"stargazers_count":9,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-26T18:11:47.325Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cedlemo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-08T09:41:06.000Z","updated_at":"2025-01-02T18:41:41.000Z","dependencies_parsed_at":"2022-09-09T08:00:40.702Z","dependency_job_id":null,"html_url":"https://github.com/cedlemo/ruby-clangc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fruby-clangc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fruby-clangc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fruby-clangc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedlemo%2Fruby-clangc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cedlemo","download_url":"https://codeload.github.com/cedlemo/ruby-clangc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243318767,"owners_count":20272136,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T22:16:04.599Z","updated_at":"2025-03-13T00:31:25.668Z","avatar_url":"https://github.com/cedlemo.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ruby-clangc\n\n[![Build Status](https://travis-ci.org/cedlemo/ruby-clangc.svg?branch=master)](https://travis-ci.org/cedlemo/ruby-clangc)\n\nruby bindings to the clang C interface\n\nThis is free software shared under the GNU GPL 3.\nThose bindings have been tested and work with :\n\n*    Clang v3.5 to v3.8.\n*    ruby 2.1 to 2.3\n\n\n## Table of Content\n\n*  [Installation](#installation)\n  *  [Dependencies](#dependencies)\n  *  [On Your system](#on-your-system)\n  *  [With Virtual Box and Vagrant](#with-virtual-box-and-vagrant)\n    *  [ArchLinux](#archlinux)\n    *  [Fedora](#fedora)\n    *  [Debian](#debian)\n*  [Examples](#examples)\n  *  [Code completion](#code-completion)\n  *  [C and C++ parser](#c-and-c++-parser)\n  *  [C simple parsing](#c-simple-parsing)\n  *  [Displaying code diagnostics](#displaying-code-diagnostics)\n*  [Documentation](#documentation)\n*  [Status](#status)\n\n## Installation\n\n### Dependencies\n*  llvm/clang v3.5 to v3.8\n*  ruby and its development libs\n*  usual development tools (gcc, make, autoconf ...)\n*  gems:\n    * rake\n    * rake-compiler\n    * minitest (optional)\n    * term-ansicolor (optional)\n\nMore informations can be found in the Vagrantfiles, in the `shell_script`\nvariable.\n\n### On your system\nthe ruby-clangc gem has not been released yet. You need to clone this github repository , build the gem and install it.\n\n```bash\n    git clone https://github.com/cedlemo/ruby-clangc.git\n    cd ruby-clangc\n    gem build clanc.gemspec\n    gem install clangc-x.x.x.gem\n```\n\n### With Virtual Box and Vagrant\n\n#### ArchLinux\n\n```bash\n    vagrant box add archlinux-x86_64 http://cloud.terry.im/vagrant/archlinux-x86_64.box\n    mkdir ruby_clang_test\n    cd ruby_clang_test\n    wget https://raw.githubusercontent.com/cedlemo/ruby-clangc/master/ArchLinux_x86_64_Vagrantfile\n    vagrant up\n    vagrant provision\n```\nThen clone the github repository, build the gem and install it like [on your system](#on-your-system).\n\n#### Fedora\n\n```bash\n    vagrant add bento/fedora-23\n    mkdir ruby_clang_test\n    cd ruby_clang_test\n    wget https://raw.githubusercontent.com/cedlemo/ruby-clangc/master/Fedora-23_Vagrantfile\n    vagrant up\n    vagrant provision\n```\nThen clone the github repository, build the gem and install it like [on your system](#on-your-system).\n\n#### Debian\n\n```bash\n    vagrant box add debian/jessie64\n    mkdir ruby_clang_test\n    wget https://raw.githubusercontent.com/cedlemo/ruby-clangc/master/Debian-Jessie-64_Vagrantfile\n    vagrant up\n    vagrant provision\n```\nThen clone the github repository, build the gem and install it like [on your system](#on-your-system).\n\n## Examples \nSee in the samples directory if you want to try those examples.\n\n### Code completion\n\n```ruby\ncindex = Clangc::Index.new(false, false)\ntu = cindex.create_translation_unit(source: filename,\n                                    args: args)\n\nreparse_options = tu.default_reparse_options\ntu.reparse(reparse_options)\n\noptions = [:include_code_patterns, :include_macros, :include_brief_comments]\ncomplete_results = tu.code_complete_at(filename,\n                                       line,\n                                       column,\n                                       options)\ncomplete_results.sort_results\n\nputs \"Diagnostics : \"\ncomplete_results.diagnostics.each do |d|\n  puts d.spelling\nend\n\nputs \"Complete :\"\ncomplete_results.results.each do |r|\n  r.completion_string.chunk_texts.each_with_index do |c, i|\n    if r.completion_string.chunk_kind(i) == Clangc::CompletionChunkKind::TYPED_TEXT\n      puts c\n    end\n  end\nend\n```\n\n###  C and C++ parser\n\n```ruby\nrequire \"clangc\"\nrequire \"fileutils\"\n\nPATH = File.expand_path(File.dirname(__FILE__))\n\nclass SourceParser\n  attr_reader :index, :source_file, :base_dir, \n              :translation_unit, :diagnostics\n  def initialize(source_file, base_dir = nil, lang = \"c\")\n    @source_file = source_file\n    @base_dir = base_dir\n    include_libs = build_default_include_libs\n    args = [\"-x\", lang] + include_libs\n    @index = Clangc::Index.new(false, false)\n    @translation_unit = @index.create_translation_unit(source: source_file,\n                                                       args: args)\n    @diagnostics = @translation_unit.diagnostics if @translation_unit\n  end\n  \n  def parse\n    cursor = @translation_unit.cursor\n    Clangc.visit_children(cursor: cursor) do |cxcursor, parent|\n      if block_given?\n        yield(@translation_unit, cxcursor, parent)\n      else\n        puts \"Please provide a block\"\n      end\n    end\n  end\n  \n  # Check if the cursor given in argument focus on \n  # the file we want to parse and not on included\n  # headers\n  def cursor_in_main_file?(cursor)\n    cursor_file = cursor.location.spelling[0]\n    main_file = @translation_unit.file(@source_file)\n    cursor_file.is_equal(main_file)\n  end\n\n  private\n\n  # Add the directories where the default headers files\n  # for the standards libs can be found\n  def build_default_include_libs\n    header_paths = []\n    if @base_dir \u0026\u0026 Dir.exist?(@base_dir)\n      @base_dir = File.expand_path(@base_dir)\n    else\n      @base_dir = File.expand_path(File.dirname(@source_file))\n    end\n    gcc_lib_base='/usr/lib/gcc/' \u003c\u003c `llvm-config --host-target`.chomp \u003c\u003c \"/*\"\n    last_gcc_lib_base = Dir.glob(gcc_lib_base ).sort.last\n    if last_gcc_lib_base\n      gcc_lib = last_gcc_lib_base + \"/include\"\n      header_paths \u003c\u003c gcc_lib\n    end\n    header_paths \u003c\u003c \"/usr/include\"\n    header_paths \u003c\u003c @base_dir\n    header_paths.collect {|h| \"-I#{h}\"}\n  end\nend\n\nclass CSourceParser \u003c SourceParser\n  def initialize(source_file, base_dir = nil)\n    super(source_file, base_dir, \"c\")\n  end\nend\n\nclass CPPSourceParser \u003c SourceParser\n  def initialize(source_file, base_dir = nil)\n    super(source_file, base_dir, \"c++\")\n  end\nend\n\nsource = \"#{PATH}/../tools/clang-3.5/Index.h\"\n\ncl35 = CSourceParser.new(source)\n\nunless cl35.translation_unit\n  puts \"Parsing failed\"\nend\n\n# This will display the names of all the functions in the header Index.h\n\ncl35.parse do |tu, cursor, parent|\n  if cl35.cursor_in_main_file?(cursor)\n    puts cursor.spelling if cursor.kind == Clangc::CursorKind::FUNCTION_DECL\n  end\n  Clangc::ChildVisitResult::RECURSE\nend\n```\n\n### C simple parsing\n\n```ruby\n#!/usr/bin/env ruby\n\nrequire \"clangc\"\n\nsource_file = \"#{File.expand_path(File.dirname(__FILE__))}/source1.c\"\n\n# Get all the necessary headers\nclang_headers_path = Dir.glob(\"/usr/lib/clang/*/include\").collect {|x| \"-I#{x}\"}\n\nindex = Clangc::Index.new(false, false)\n\ntu = index.create_translation_unit_from_source_file(source_file, \n                                                    clang_headers_path)\nexit unless tu\ncursor = tu.cursor\n\ndef pretty_print(cursor_kind, cursor)\n  printf(\"%s %s line %d, char %d\\n\",\n         cursor_kind,                 \n         cursor.spelling,\n         cursor.location.spelling[1],\n         cursor.location.spelling[2])\nend\n\nClangc.visit_children(cursor: cursor) do |cursor, parent| \n  if cursor.location.spelling[0].name == source_file\n    case cursor.kind \n    when Clangc::CursorKind::TYPEDEF_DECL\n      pretty_print(\"typedef     \", cursor)\n    when Clangc::CursorKind::STRUCT_DECL\n      pretty_print(\"structure   \", cursor)\n    when Clangc::CursorKind::ENUM_DECL\n      pretty_print(\"Enumeration \", cursor)\n    when Clangc::CursorKind::UNION_DECL\n      pretty_print(\"Union       \", cursor)\n    when Clangc::CursorKind::FUNCTION_DECL\n      pretty_print(\"Function    \", cursor)\n      arguments = cursor.type.arg_types\n      puts \"\\t#{arguments.size} argument(s)\"\n        arguments.each do |a|\n        puts \"\\t-\\t\" + a.spelling \n      end\n    end\n  end\n  Clangc::ChildVisitResult::RECURSE\nend\n```\n\n### Displaying code diagnostics\n\n```ruby\n#!/usr/bin/env ruby\nrequire \"clangc\"\n\n# excludeDeclsFromPCH = 0, displayDiagnostics=0\ncindex = Clangc::Index.new(false, false)\n\nclang_headers_path = Dir.glob(\"/usr/lib/clang/*/include\").collect {|x| \"-I#{x}\"}\nsource = \"#{File.expand_path(File.dirname(__FILE__))}/list.c\"\n\ntu = cindex.parse_translation_unit(source: source, \n                                   args: clang_headers_path, \n                                   flags: :none)\n\nexit unless tu\n\ntu.diagnostics.each_with_index do |diagnostic, index|\n  puts \"################### Diagnostic N° #{index + 1 } #####################\"\n  puts \"Default display options:\"\n  puts  \"\\t #{diagnostic.format(Clangc::default_diagnostic_display_options)}\"\n  puts \"None:\"\n  puts  \"\\t #{diagnostic.format(0)}\"\n  puts \"None + Source Location:\"\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_SOURCE_LOCATION\n  puts  \"\\t #{diagnostic.format(:display_source_location)}\"\n  puts \"None + Source Location + Column:\"\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_SOURCE_LOCATION |\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_COLUMN\n  puts \"\\t #{diagnostic.format([:display_source_location, :display_column])}\"\n  puts \"None + Source Location + Column + Category Name:\"\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_SOURCE_LOCATION |\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_COLUMN |\n  # Clangc::DiagnosticDisplayOptions::DISPLAY_CATEGORY_NAME\n  puts \"\\t #{diagnostic.format([:display_source_location,\n                                :display_column,\n                                :display_category_name])}\"\nend\n```\n## Documentation\n\nAll the functions are documented with rdoc (maybe yard when I will have \nthe time) in the *doc* directory. If you want to update it, or re-generate it just do:\n\n    rake rdoc\n\n## Status\nWhen ruby-clangc is installed, you can try the *tools/status.rb* script in order to see the current status and to see what we can do with ruby-clangc. You will need the gem `term-ansicolor`\n\n### functions wrapped:\n\n*    185/257 functions wrapped =\u003e 71.98443579766537%\n\n### classes wrapped:\n\n*    CXIndex\n*    CXTranslationUnit\n*    CXDiagnostic\n*    CXFile\n*    CXSourceRange\n*    CXSourceLocation\n*    CXCursor\n*    CXType\n*    CXCursorSet\n*    CXModule\n*    CXCompletionString\n*    CXCodeCompleteResults\n*    CXCompletionResult\n\n\nruby-clangc ruby bindings for the C interface of Clang\nCopyright (C) 2015-2016 Cédric Le Moigne cedlemo \u003ccedlemo@gmx.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedlemo%2Fruby-clangc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcedlemo%2Fruby-clangc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedlemo%2Fruby-clangc/lists"}