Skip to content

Instantly share code, notes, and snippets.

@wanabe
Last active December 15, 2015 13:28
Show Gist options
  • Select an option

  • Save wanabe/5267097 to your computer and use it in GitHub Desktop.

Select an option

Save wanabe/5267097 to your computer and use it in GitHub Desktop.

Patch by mrbgems

Abstract

I want to introduce the patching rule by mrbgems to mruby core.

Background

First, I want to make mruby-JIT mrbgems. https://github.com/miura1729/mruby

So I have to patch to mruby because JIT is too low level.

Proposal

I introduce how to patch.

example

See: https://github.com/wanabe/mruby-jit

core/src

If you wish to include some source files in mruby core, push files into core/src directory.

core/src/.{c,cc,cpp,m,asm,S} is required by libmruby and libmruby_core as same as src/.{c,cc,cpp,m,asm,S}, original mruby source files.

rake file

You can patch to mruby core to use MRuby::Build#patch in rakefile. Like this:

  patch "path/from/mruby/root", "path/to/patch"

or

  patch "path/from/mruby/root", __FILE__ do ... end

Patched files is pushed to build/(build-target)/original/path. In example, patched vm.c for host, is in build/host/src/vm.c.

1st argument is patch target.

2nd argument is patch file. This file is required by patched file. So if you update this file, rakefile update patched file automatically.

When MRuby::Build#patch receive a block, patch file isn't read content but use time stamp to update. block is evaluated as patching rule.

patched sources and headers

patched c-sources come into use in place of original ones. Because rule of making object files is overwritten by MRuby::Build#patch.

patched headers is same. Because build/(build-target)/include add to top of include_paths of cc and cxx.

Patch syntax

You can write patches in Ruby DSL.

state

Patching state has @line, @match, and @mark.

@line is index of current line. most methods , like MRuby::PatchTarget#search, can change @line.

@match is last MatchData.

@mark is index of marked line and updated by MRuby::PatchTarget#mark or MRuby::PatchTarget#search. Patching range is represented by @mark..@line.

methods

  • insert(String)
    • insert string to current line.
  • mark
    • mark current line.
  • delete
    • delete lines @mark..@line and set @line = @mark.
  • change(String)
    • same as delete.insert(str).
  • each do ... end | each(pattern) do ... end
    • enumerate each line between @mark..@line. If pattern is given, enumerate line only pattern === line.
  • rest
    • set @mark = @line and @line to last line. If block given, eval block and reset line last value.
  • seek(*patterns)
    • down @line from current line by pattern, following:
      • pattern is Integer-- treat as offset. eval @line += pattern.
      • pattern is :mark-- set mark. same as seek(*patterns_before_mark).mark.seek(*patterns_after_mark)
      • other -- seek the line what pattern === line.

Why need DSL

patch(1), Unix command, is useful. But in this case patch(1) is not fit unfortunately, I guess.

patch may be old in future

mruby core get change day by day. So someday, patch write once may be too old. Of course DSL doesn't keep patch available on eternity. But DSL can extend the life cycle than patch(1), I guess.

conflict between patches

patch(1) needs some lines to identify target line. For example, A gem and B gem want to extend same struct, patching will be failed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment