Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

mrbgems #479

Merged
merged 106 commits into from
@bovi

mrbgems is a library manager to integrate C and Ruby extensions in an easy and standardised way into mruby.

This is a follow up to #470

After talking shortly to matz on the RubyKaigi in Sapporo I have worked over the last week to bring this implementation up to an usable state. The current implementation can integrate extensions build in C or Ruby.

Documentation

I have written a documentation for mrbgems (located under doc/mrbgems) and prepared two example Gems (one pure Ruby extension and one pure C extension).

Test

Test of gems

A Gem can have tests which will be automatically integrated by the build process into mrbtest.

Test of mrbgems

I have tested C and Ruby Extension on:

Mac OS X (10.8.2)
Darwin 12.2.0 Darwin Kernel Version 12.2.0; root:xnu-2050.18.24~1/RELEASE_X86_64 x86_64

Ubuntu 64bit
Linux 3.2.0-23-generic Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

Overhead

There is no overhead anymore in case mrbgems isn't used!!!
I have check the overhead of the implementation. In case no Gem exists the impact to the size of the mruby binary is:

before:

550452 (538K) mirb
534828 (522K) mrbc
550224 (537K) mruby

after:

These binaries were compiled on Mac OS X (10.8.2) with "-g -O3". The overhead is only 336 bytes.

bovi added some commits
@bovi bovi change global Makefile by adding mrbgems to it 738a877
@bovi bovi Change mrblib Makefile to include gems 50c21a9
@bovi bovi Add init function for gems to init of core d3d21cb
@bovi bovi make mrbc aware of the gem init cd72971
@bovi bovi Add a first implementation of mrbgems with one fixed MD5 gem f89e722
@bovi bovi Add TODOs to finalize gems a941934
@bovi bovi Small modifications for location 85bc533
@bovi bovi Relocated md5 source 0101e47
@bovi bovi Remove old location of md5 source 3ee1565
@bovi bovi Relocate files ac235e2
@bovi bovi Built generator for an variable amount of gems c6a520c
@bovi bovi remove second gem ea68cb1
@bovi bovi Some additional changes to compile properly 17c8770
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems c0ff4fe
@bovi bovi Ignore generated files 48c84cb
@bovi bovi Modify information messages e742558
@bovi bovi add hello world test program ab548b1
@bovi bovi Add default makefile for Gems 19fa4a0
@bovi bovi Integrate tests into mrbgems 9a11c45
@bovi bovi Remove TODO. This point is finished a8d418d
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems 3d32380
@bovi bovi Optimize Makefile f93572c
@bovi bovi Add Support for Ruby Extensions, C Extensions and Test Integration d6f2f55
@bovi bovi Remove symbol recreation where not necessary 81225a9
@bovi bovi Modify README for examples 668b228
@bovi bovi Rename Gem Examples 80b7f45
@bovi bovi Move Gem Tests into the main Test target 0e7d5a2
@bovi bovi Optimize Makefiles df91989
@bovi bovi Fix Makefile 2a6152a
@bovi bovi Another fix for Makefile 7b8b3c0
@bovi bovi Catch some corner cases 62b652c
@bovi bovi Modify generator for using printf b4c4fce
@bovi bovi Beautify generator 97a91d2
@bovi bovi Empty GEM directory 316edbe
@bovi bovi Ignore gitignore cad954a
@bovi bovi Fix initializing of generator and beautify generator 0832e26
@bovi bovi Remove gem_empty f699d8e
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems 3fb943e
@bovi bovi Improve Gem Readme file a7cb973
@bovi bovi Improve Gem Readme Source 96afe4b
@bovi bovi Improve documentation for Gem and add limitations ad37ddd
@bovi bovi Spell fix in mrbgems Readme d4631f2
@bovi bovi Add location of gem to readme 78a053a
@bovi bovi Add a limitation for object files with C Extension 81bff9a
@bovi bovi Fix for not existing tests 6e589f5
@bovi bovi Add accidently removed comment 4d12ff4
@bovi bovi used comments to contributer style 993b37c
@bovi bovi Ignore built files of gem 5b25723
@takahashim

It's great if mrbgems support (the difference of) target OS and architectures, IMHO. Do you have any idea?

@bovi

with cmake it should be easy possible. if matz accepts this change I can also work on modifing the existing Makefiles to support a TARGET_CC compiler. But then we need to change the Makefile for mrbc and mruby too. Due to the reason that at the moment for all compilation the same compiler is used.

@takahashim

Some features, like Time(Timer) , IO and Socket, may have different API sets and different implementations with each OSes, each archs.
The easy way is creating different mrbgems with naming convention, but I'd love to see and use better solutions.

@bovi

I understand your point. I would suggest a directory structure like:
src/x86
src/x86_64
src/win32
etc.

And then replace architecture specific files automatically.

What do you think? Any further ideas?

@takahashim

Is it like that?

src/x86 (is it Linux and OS X?)
src/win32
src/ios
src/uclinux
src/freertos or src/lpc2388-freertos

I'm afraid that each gems authors can support only one or two platforms.
It's great if gems developers can create their archives or repositories for other platforms independently and share them.
But it's difficult for RubyGems, so we do not need to worry.

@bovi

I think we should support an "ARCH" like variable and based on them a specific code path would be choosen. I understand your point that it is hard for on developer to program support for all architectures but I think it should be possible to provide a way to integrate different architecture support in one and the same Gem. If one Gem can only run for one architecture I think the quality and features will be dramatically different. specially if the Gem also contains non architecture specific code.

I think we should not target RubyGems support. The integration should be as simple as possible so that everybody can by hand also adapt an existing Gem to the local situation. Specially in embedded systems it is very hard if not impossible to provide a proper working system for everybody. So it should be easy for them to adapt to system specific things.

@sogabe

It is awesome feature for me. I am so happy if mrbgem is loaded dynamically.

@bovi

Hi sogabe,

what kind of dynamic loading do you think about? Due to the reason that at the moment the "gems" are compiled into libmruby they can't be changed at a later time while the program is running. I could imagine it would be possible to pass a gem to "mruby" which then will include it into the current execution process. That isn't to hard to implement I suppose. But I'm not sure if that is what you understand under dynamic. If you mean the "gem" should be reloaded dynamic during the execution time then I'm not sure how to implement that at the moment. As you might know mruby doesn't support the same "require" functionality as vanilla Ruby at the moment. And after talking to matz I'm not really sure if it will ever be included into plain mruby due to the reason that we would need file system handling for this feature.

Could you detail the use case you are wishing for dynamic loading?

/daniel

@sogabe
@bovi

Hi Takashi,

I saw your mruby repository. It is quite impressive what kind of features you have already implemented. I'm really looking forward if we can find an easy way to integrate your functionalities.

I'm wondering if we can make some modifications to mrbgems in the following manner:

  • every Gem is building a "GEMNAME.a" archive file
  • during the buildprocess the user can define if he wants to compile all functionalities in
  • additional he has the possibility at a later time to start mruby maybe in this way: "mruby -G GEMNAME"
  • the feature would dynamically bind the gem functionality into mruby
  • if mruby is started without, the gem isn't loaded

Additional I could imagine we can generate a ruby method which calls the c init method to initialize all features. That would probably the closest thing to what you need due to the reason that I understand you in a way that you need to add gem functionality during runtime.

Is this the kind of functionality you would need? If yes I think that should be possible to integrate. But first lets see what @matz says to all of this. Maybe there are still some no-gos with the current implementation which have to be changed nevertheless.

Regards
Daniel

@beoran

I think the idea of compiling the gem down to a (lib)gemname.a or gemname.lib static library is a good idea. It will be easier to modify the CMake build scripts to support Gems like that. People who want a certain extension then can use another their own build script to select which gems they want to incorporate. I could probably whip up a CMake macro FindMrubyGem to facilitate this.

But for dynamic loading of C extensions at run time it's necessary to use shared libraries, and mruby would need to incorporate shared library lading which is OS specific. Probably that's undesirable. So I think only ruby files could b loaded at runtime. C extensions will need to be linked statically...

@sogabe

Hi, Daniel,
That kind of functionality is worth for us. Furthermore, It is more useful to have a capability to choose which gems to be embedded at a build time.

Daniel Boven... and others added some commits
Daniel Bovensiepen Merge remote-tracking branch 'upstream/master' into mrbgems cdb72a0
@bovi bovi Merge new change e1e3694
@bovi bovi Fix merge fcaeec5
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems c3bd1c1
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems d8234a4
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems e246b79
@bovi bovi Modify comments for generator 389ceaf
@bovi bovi Add C and Ruby Extension Example Mixed 83fdc3d
@bovi bovi Modify C Extension bc26a48
@bovi bovi Modify Ruby Extension f591d11
@bovi bovi Improve building of Gems to single Archive Files f97e3fa
@bovi bovi Improve Including File to build single archive Files f30eedd
@bovi bovi Improve Generator by handling Ruby and C Extensions in the same way a9df6f8
@bovi bovi Include dynamically GEMs into mrbtest a9513c1
@bovi bovi Include dynamically GEMs into mirb 1e4d20a
@bovi bovi Include dynamically GEMs into mruby ed92a86
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems 754c853
@bovi bovi Make GEM build choosable. Respect GEMS.active file for choices of whi…
…ch GEM to build
953cbff
@bovi bovi Merge remote-tracking branch 'upstream/master' into mrbgems c794d1c
@bovi bovi Adapt new GEM compile process to ignore list 8c86ee9
@bovi bovi Rename GEM init file d1efcb4
@bovi bovi Clean GEM Generator a bit more 74121d6
@bovi bovi Deactivate / Activate GEMs Flag introduced into Makefile dbde619
@bovi bovi Deactivate / Activate GEMs Flag introduced into mrbconf.h 6ebc191
@bovi bovi Deactivate / Activate GEMs Flag introduced into src/init.c 35edbb0
@bovi bovi Deactivate / Activate GEMs Flag introduced into mrbtest 2a2e206
@bovi bovi Deactivate / Activate GEMs Flag introduced into mirb a26e5c0
@bovi bovi Deactivate / Activate GEMs Flag introduced into mruby 4f55a3e
@bovi bovi Deactivate / Activate GEMs Flag introduced into mrbc 4e2161c
@bovi

Thanks for all the requests and comments. After talking to @takahashim in Matsue I have integrated now the following additional things which seem to be most important for other users:

  • mrbgems can be (de-)activated
  • every GEM builds a "gem.a" file in his directory which can be used to integrate the functionality
  • it is now possible to build pure Ruby, pure C and mixed C and Ruby GEM extensions
  • it is now possible to build your own customized GEM with his own build process
  • there is now a file called "GEMS.active" which defines which GEMs will be build

Here a little bit more in detail the most important improvements:

(de-)activate mrbgems

I introduced the following variables:

  • ENABLE_GEMS / DISABLE_GEMS in include/mrbconf.h
  • ENABLE_GEMS = (true|false) in Makefile

I have set the default value to be deactivated. In case you deactivate the mrbgems functionality there is no overhead due to mrbgems at all.

GEMS.active

I introduced a file mrbgems/GEMS.active. Every GEM name which is included in this file will be build during build time. Every not defined GEM will be skipped.

gem.a

Every GEM now needs to build a file called gem.a in his own directory. It doesn't matter how your build process is working as long as a "make" inside of your GEM creates a gem.a file. The rest is happening automatically. I improved the "Makefile4gem" too. So that building a standard GEM is now even easier.

Fazit

I hope that most of your requests are now integrated. I also hope you find the time to have a look at the code. So maybe we can convince @matz together about this solution.

Looking forward to feedback.

Outlook

In case the current implementation is interesting enough to be considered for integration, the next target would be to build a small program to choose the GEMs to build and create the file GEMS.active automatically. I imagine something like "make gems" which opens a dialog to choose possible GEMs.

@mauceri

It would be very important for me to have this pull request accepted, it would be a huge time saving.

@beoran

If this gets accepted in core, I'll make this idea work with cmake.

However, I have a few remarks. First, this type of "gems" can only be built together with mruby in a sub dir of mruby. It would be nice for distribution and development if gems could be compiled somewhat more independently. Aslo, I'm not sure that naming all gems simply gem.a is a good idea. Maybe mruby-package-gem.a would be better if possible? Think of what the Debian packagers will do :p

@bovi

Hi beoran,

I agree to all of your remarks. And so I implemented all of them.

mrbgems now builds an archive file for every gem which has the structure mrb-GEMNAME-gem.a Additional I made the build process more flexible so that it is now possible to handle GEMs outside of the mruby tree. Only dependencies kept is the GEMS.active file, which now has to be feeded with an absolute path to your GEM. But the GEM can be located where every you want, no temporary build files of the particular GEM will be put into the mruby tree except the generated test code.

@beoran

Great! You could probably also make the location of GEMS.active flexible with an environment variable, but that's a nitpick, I guess. Anyway, thanks for your fast changes! :)

@bovi

Yeah this isn't to hard todo neither. I have a look at it tomorrow, to late today already (-: Thanks for your feedback!

@bovi

So I took the time today and removed the last static bit in the mrbgems build process. GEMS.active can now be located everywhere. mrbgems also now maintains a MRUBY_ROOT so that the GEM author doesn't need to know the location of the mruby tree. That makes it possible to build a GEM completly independent from the mruby tree.

@beoran

Looks great! I have my work cut out if I want to to port this to CMake. :)

@mauceri

Daniel, do you have a sample showing how to use mrbgem ?

@bovi

@beoran hehe, looking forward to that :-)

@mauceri have a look under doc/mrbgems I have created three examples which shows GEMs written in pure C, pure Ruby and mixed C and Ruby

@mauceri
@bovi

I've added some more documentation to doc/mrbgems/README.md on how to activate and use mrbgems.

@mauceri
@schmurfy

I am really looking forward having this merge, having a standard way of sharing libraries is one of the first question I asked myself about when I first looked at mruby, without this it can only be chaos with forks everywhere.

@mauceri
@sogabe

I was really understand how to build a mrubygem. In my environment(Ubuntu/amd64), link error was occur in link-phase.
I would prefer change the order of libraries in MakefileGemList as follows:

GEM_LIST := (path_to_mrb_gem_a)
GEM_ARCHIVE_FILES := $(MRUBY_ROOT)/mrbgems/gem_init.a
GEM_ARCHIVE_FILES += $(GEM_LIST)
@bovi

Hi @sogabe, thanks for the notice on Ubuntu/amd64. I integrated your suggestion which makes totally sense.

@sogabe

Thanks a lot, @bovi. I can finally build the code without compile errors.

@bovi

Great. Tell me if you have any other suggestions or ideas.

@tsahara-iij tsahara-iij referenced this pull request in iij/mruby
Closed

mruby gem が欲しい #18

@sogabe

I would like to implement a function to resolve dependencies on each gems.I think that kind of function might be like a FreeBSD's ports.
Ideally, OSGi bundle management framework for Java is more powerful, but for now, ports-like system is good enough to us.

@bovi

Hi @sogabe,

I think dependencies are neat. How would you link between them? At the moment I didn't thought about having a unified repository (as long as the patch isn't accepted it might make nevertheless no sense) but how would you suggest a relationship model with a decentral repository? Would you link to specific repos directly? Or would you actually consider a unified repository?

/daniel

@mauceri

Hi Daniel,

I'm working on mrbgems using the examples you put in doc, is there an automated way to include the gem tests in the general tests ? In fact what I do not grasp is the mechanism allowing to automatically add the gems in the main library. I maybe missed something.
I did the following:
1. I setup the root Makefile as described in the doc
2. I copied c_and_ruby_extension_example in the g folder of mrbgems
3. I added the full path to it in GEMS.active

make clean test work fine you'll find the trace below.
One can see mirb is linked to the gem lib:

  gcc -o ../../bin/mirb -g -O3 ../../src/../tools/mirb/mirb.o ../../lib/libmruby.a
    /Users/cmauceri/Documents/IOS/mruby/mrbgems/gem_init.a      
    /Users/cmauceri/Documents/IOS/mruby/mrbgems/g/c_and_ruby_extension_example/mrb-
     c_and_ruby_extension_example-gem.a  -     lm

but when I launch mirb and try a test I get this:

CRubyExtension.respond_to? :ruby_method
NameError: uninitialized constant CRubyExtension

Any idea of what I could doing wrong ?

Cheers.
Christian.

 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/src
 rm -f ../lib/libmruby_core.a ./array.o ./ascii.o ./cdump.o ./class.o ./codegen.o ./compar.o ./crc.o ./dump.o .     /encoding.o ./enum.o ./error.o ./etc.o ./gc.o ./gvar.o ./hash.o ./init.o ./init_ext.o ./kernel.o ./load.o ./math.o .     /numeric.o ./object.o ./parse.o ./parse.tab.o ./pool.o ./print.o ./proc.o ./range.o ./re.o ./regcomp.o ./regenc.o .     /regerror.o ./regexec.o ./regparse.o ./require.o ./sprintf.o ./st.o ./state.o ./string.o ./struct.o ./symbol.o .     /time.o ./unicode.o ./us_ascii.o ./utf_8.o ./variable.o ./vm.o   ./y.tab.o ./y.tab.c
 rm -f ./array.d ./ascii.d ./cdump.d ./class.d ./codegen.d ./compar.d ./crc.d ./dump.d ./encoding.d ./enum.d ./error.     d ./etc.d ./gc.d ./gvar.d ./hash.d ./init.d ./init_ext.d ./kernel.d ./load.d ./math.d ./numeric.d ./object.d ./parse     .d ./parse.tab.d ./pool.d ./print.d ./proc.d ./range.d ./re.d ./regcomp.d ./regenc.d ./regerror.d ./regexec.d .     /regparse.d ./require.d ./sprintf.d ./st.d ./state.d ./string.d ./struct.d ./symbol.d ./time.d ./unicode.d .     /us_ascii.d ./utf_8.d ./variable.d ./vm.d ./y.tab.d
 rm -f ./y.tab.o ./minimain.o ./y.tab.d ./minimain.d
 -- CLEAN mrbgems --
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -MMD -c      /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.c -o /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.o
 Build the generator which creates the driver and Gem Makefile
 gcc -o /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator -Wall -Werror-implicit-function-declaration -g -O3 -     MMD -I. -I./../include /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.o
 Cleanup Gems
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator makefile "GEMS.active" > g/Makefile
 make clean -C g ACTIVE_GEMS="GEMS.active" MRUBY_ROOT='/Users/cmauceri/Documents/IOS/mruby'
 rm -f *.c *.d *.rbtmp *.ctmp *.o mrbtest
 rm -f mrb-c_and_ruby_extension_example-gem.a gem_mixlib.o gem_mixlib.c gem_mrblib_header.ctmp gem_mrblib_irep.ctmp      gem_mixlib_init.ctmp gem_mrblib.rbtmp
 Gem 'c_and_ruby_extension_example' is clean
 rm -f gem_init.c *.o *.d /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator g/Makefile g/MakefileGemList gem_init     .a
 make clean -C ../../mrblib CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -g -O3'
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/mrblib
 rm -f ../bin/mrbc mrblib.o mrblib.c mrblib.rbtmp mrblib.ctmp mrblib.d ../lib/libmruby.a
 make clean -C ../mrbc CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -g -O3'
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/tools/mrbc
 rm -f ../../bin/mrbc ../../src/../tools/mrbc/mrbc.o
 rm -f ../../src/../tools/mrbc/mrbc.d
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/tools/mruby
 rm -f /Users/cmauceri/Documents/IOS/mruby/bin/mruby /Users/cmauceri/Documents/IOS/mruby/src/../tools/mruby/mruby.o
 rm -f /Users/cmauceri/Documents/IOS/mruby/src/../tools/mruby/mruby.d
 make clean -C ../../mrblib CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -g -O3'
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/mrblib
 rm -f ../bin/mrbc mrblib.o mrblib.c mrblib.rbtmp mrblib.ctmp mrblib.d ../lib/libmruby.a
 make clean -C ../mrbc CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -g -O3'
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/tools/mrbc
 rm -f ../../bin/mrbc ../../src/../tools/mrbc/mrbc.o
 rm -f ../../src/../tools/mrbc/mrbc.d
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/tools/mirb
 rm -f ../../bin/mirb ../../src/../tools/mirb/mirb.o
 rm -f ../../src/../tools/mirb/mirb.d
 make: removing targets, objects and depend files of /Users/cmauceri/Documents/IOS/mruby/test
 rm -f mrbtest.o mrbtest.c mrbtest.rbtmp mrbtest.ctmp mrbtest.d driver.d driver.o mrbtest.o mrbtest
 rm -f mrubytest.rb mrubytest.mrb mrubytest.rb.report mrubytest.mrb.report
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c array.c -o array.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c ascii.c -o ascii.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c cdump.c -o cdump.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c class.c -o class.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c codegen.c -o codegen.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c compar.c -o compar.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c crc.c -o crc.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c dump.c -o dump.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c encoding.c -o encoding.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c enum.c -o enum.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c error.c -o error.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c etc.c -o etc.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c gc.c -o gc.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c gvar.c -o gvar.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c hash.c -o hash.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c init.c -o init.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c init_ext.c -o init_ext.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c kernel.c -o kernel.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c load.c -o load.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c math.c -o math.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c numeric.c -o numeric.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c object.c -o object.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c parse.c -o parse.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c parse.tab.c -o parse.tab.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c pool.c -o pool.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c print.c -o print.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c proc.c -o proc.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c range.c -o range.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c re.c -o re.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c regcomp.c -o regcomp.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c regenc.c -o regenc.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c regerror.c -o regerror.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c regexec.c -o regexec.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c regparse.c -o regparse.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c require.c -o require.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c sprintf.c -o sprintf.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c st.c -o st.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c state.c -o state.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c string.c -o string.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c struct.c -o struct.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c symbol.c -o symbol.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c time.c -o time.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c unicode.c -o unicode.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c us_ascii.c -o us_ascii.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c utf_8.c -o utf_8.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c variable.c -o variable.o
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c vm.c -o vm.o
 bison -o ./y.tab.c ./parse.y
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -c ./y.tab.c -o ./y.tab.o
 ar r ../lib/libmruby_core.a ./array.o ./ascii.o ./cdump.o ./class.o ./codegen.o ./compar.o ./crc.o ./dump.o .     /encoding.o ./enum.o ./error.o ./etc.o ./gc.o ./gvar.o ./hash.o ./init.o ./init_ext.o ./kernel.o ./load.o ./math.o .     /numeric.o ./object.o ./parse.o ./parse.tab.o ./pool.o ./print.o ./proc.o ./range.o ./re.o ./regcomp.o ./regenc.o .     /regerror.o ./regexec.o ./regparse.o ./require.o ./sprintf.o ./st.o ./state.o ./string.o ./struct.o ./symbol.o .     /time.o ./unicode.o ./us_ascii.o ./utf_8.o ./variable.o ./vm.o   ./y.tab.o
 cat ./*.rb > mrblib.rbtmp
 make -C ../tools/mrbc CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -g -O3'
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I../../src -I../../src/../include -c ../../src/..     /tools/mrbc/mrbc.c -o ../../src/../tools/mrbc/mrbc.o
 gcc -o ../../bin/mrbc ../../src/../tools/mrbc/mrbc.o ../../lib/libmruby_core.a -lm
 ../bin/mrbc -Bmrblib_irep -omrblib.ctmp mrblib.rbtmp; cat init_mrblib.c mrblib.ctmp > mrblib.c
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I../src -I../include -c mrblib.c -o mrblib.o
 cp ../lib/libmruby_core.a ../lib/libmruby.a
 ar r ../lib/libmruby.a mrblib.o
 -- MAKE mrbgems --
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -MMD -c      /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.c -o /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.o
 Build the generator which creates the driver and Gem Makefile
 gcc -o /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator -Wall -Werror-implicit-function-declaration -g -O3 -     MMD -I. -I./../include /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator.o
 Generate Gem List Makefile
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator makefile_list "GEMS.active" > g/MakefileGemList
 Generate Gem Makefile
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator makefile "GEMS.active" > g/Makefile
 Build all gems
 make -C g MRUBY_ROOT='/Users/cmauceri/Documents/IOS/mruby' ACTIVE_GEMS="GEMS.active"
 Building Gem 'c_and_ruby_extension_example'
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator gem_mrblib "GEMS.active" > gem_mrblib_header.ctmp
 cat mrblib/example.rb > gem_mrblib.rbtmp
 /Users/cmauceri/Documents/IOS/mruby/bin/mrbc -Bgem_mrblib_irep_c_and_ruby_extension_example -ogem_mrblib_irep.ctmp      gem_mrblib.rbtmp
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator gem_mixlib c_and_ruby_extension_example "GEMS.active" >      gem_mixlib_init.ctmp
 cat gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp > gem_mixlib.c
 gcc -Isrc -I/Users/cmauceri/Documents/IOS/mruby/include -I/Users/cmauceri/Documents/IOS/mruby/src -I. -O3 -g -Wall -     Werror-implicit-function-declaration   -c -o gem_mixlib.o gem_mixlib.c
 ar rs mrb-c_and_ruby_extension_example-gem.a  src/example.o gem_mixlib.o
 Generate Gem driver
 /Users/cmauceri/Documents/IOS/mruby/mrbgems/generator gem_init "GEMS.active" > gem_init.c
 Build the driver which initializes all gems
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include -MMD -c gem_init.c -o gem_init.o
 ar rs gem_init.a gem_init.o
 make -C tools/mruby --no-print-directory CC='gcc' LL='gcc' ALL_CFLAGS='-Wall -Werror-implicit-function-declaration -     g -O3' ENABLE_GEMS='true' ACTIVE_GEMS='GEMS.active' MRUBY_ROOT='/Users/cmauceri/Documents/IOS/mruby'
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I/Users/cmauceri/Documents/IOS/mruby/src -     I/Users/cmauceri/Documents/IOS/mruby/src/../include -c /Users/cmauceri/Documents/IOS/mruby/src/../tools/mruby/mruby.     c -o /Users/cmauceri/Documents/IOS/mruby/src/../tools/mruby/mruby.o
 gcc -o /Users/cmauceri/Documents/IOS/mruby/bin/mruby -g -O3 /Users/cmauceri/Documents/IOS/mruby/src/..     /tools/mruby/mruby.o /Users/cmauceri/Documents/IOS/mruby/lib/libmruby.a      /Users/cmauceri/Documents/IOS/mruby/mrbgems/gem_init.a      /Users/cmauceri/Documents/IOS/mruby/mrbgems/g/c_and_ruby_extension_example/mrb-c_and_ruby_extension_example-gem.a  -     lm
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I../../src -I../../src/../include -c ../../src/..     /tools/mirb/mirb.c -o ../../src/../tools/mirb/mirb.o
 gcc -o ../../bin/mirb -g -O3 ../../src/../tools/mirb/mirb.o ../../lib/libmruby.a      /Users/cmauceri/Documents/IOS/mruby/mrbgems/gem_init.a      /Users/cmauceri/Documents/IOS/mruby/mrbgems/g/c_and_ruby_extension_example/mrb-c_and_ruby_extension_example-gem.a  -     lm
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I./../src -I./../include -c driver.c -o driver.o
 cat ./assert.rb ./t/*.rb > mrbtest.rbtmp
 ../bin/mrbc -Bmrbtest_irep -omrbtest.ctmp mrbtest.rbtmp
 cat /Users/cmauceri/Documents/IOS/mruby/mrbgems/g/c_and_ruby_extension_example/test/*.rb  > mrbgemtest.rbtmp
 /Users/cmauceri/Documents/IOS/mruby/bin/mrbc -Bmrbgemtest_irep -omrbgemtest.ctmp mrbgemtest.rbtmp
 cat init_mrbtest.c mrbtest.ctmp ../mrbgems/g/mrbgemtest.ctmp > mrbtest.c
 gcc -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I./../src -I./../include -c mrbtest.c -o mrbtest.o
 gcc -o mrbtest -g -O3 driver.o mrbtest.o ../lib/libmruby.a /Users/cmauceri/Documents/IOS/mruby/mrbgems/gem_init.a      /Users/cmauceri/Documents/IOS/mruby/mrbgems/g/c_and_ruby_extension_example/mrb-c_and_ruby_extension_example-gem.a -     lm
 cat ./assert.rb ./t/*.rb ./report.rb > mrubytest.rb
 ../bin/mrbc mrubytest.rb
 # exec mrbtest
 ./mrbtest
 mrbtest - Embeddable Ruby Test

 This is a very early version, please test and report errors.
 Thanks :)

 ....................................................................................................................     ....................................................................................................................     ....................................................................................................................     ....................................................................................................................     .................................
 Total: 497
    OK: 497
    KO: 0
 Crash: 0
  Time: 0.005391 seconds

 # exec mruby test with ruby script
 mrubytest.rb success.

 # exec mruby test with mrb file
 mrubytest.mrb success.
@mauceri

Daniel,
sorry, my guilt, something went wrong with my different merges and I had an old lod_irep_file and an incomplete mrbconf.h without

 #ifndef DISABLE_GEMS
 #define ENABLE_GEMS
 #endif

Everything works fine finally.
Cheers.
Christian.

@bovi

Morning @mauceri,

it is great that everything works for you again. Nevertheless here is a small explanation of the build process:

  • generator creates a Makefile based on the GEM.active file
  • this Makefile will be executed -> call make in every gem directory
  • during the build of mirb and mruby the also generated Makefile g/MakefileGemList will be used to get a list of all GEM libraries
  • when executing "make test" the build process should automatically grab the file "g/mrbgemtest.ctmp" which includes all compiled test code of every GEMs "test/*" directory. this will be integrated into mrbtest so that all your tests shoud be executed too.

I think the most difficult part to understand is the generation of the Makefile. I decided to generate the Makefile due to the reason that reading file and directory structures inside of a Makefile is very platform dependent. In opposite in C we can make it quite platform independent.

Just a small notice: I think your problem came due to the reason that @matz simplified the functionality of loading IREP. I merged that change yesterday and had to modify mrbtest a bit to be consistent to these changes of mrb_load_irep.

Regards
Daniel

@matz
Owner

I reviewed the pull-request, and it seems fine, except for generator.c uses non-C99 functionality like unistd.h and dirent.h. Is there any way to avoid them? Maybe you can use wildcard expansion in Makefile.

@bovi

Thanks @matz for the review. I will remove non C99 features.

@bovi

Hi @matz,

I removed all special dependencies. What is left now is:

  • string.h
  • stdio.h
  • stdlib.h

That should be all covered by C99.

At the time of my integration test with the latest head I notice that you just implemented some minutes ago a new macro in src/init.c. I adapted this DONE; pattern also for mrbgems instead of using mrb_gc_arena_restore directly.

@matz
Owner

Thank you!

@matz matz merged commit f521738 into from
@mauceri

Great news, congratulations Daniel !

@schmurfy

great job :)
It would be good to mention the existence of mrbgems in the main README file so that people who did not follow this pull request knows about it.

@masuidrive

Great Job, bovi!
I have long hope it!!

@mauceri
@bovi

@masuidrive Yes. I'm wondering if we can both work on some of your mobiruby parts like cfunc to port it to a GEM. I would love to use cfunc for other things than ios (-:

@mattn

Can anyone please explain how to make mrbgems for existing mruby extension?

@mattn

How to add the path of ruby_extension_example into GEMS.active ? in manualy !? isn't mrbgem command ?

@bovi

Hi @mattn, at the moment you have to do it manual. There is no command yet. You have to put in the full absolute path to you gem.

@mattn

Hi @bovi . Thanks to your great work. I'm wondering what is mrbgems

  • dynamic loading module for mruby executable ?
  • Or, compilable archive like -luv ?

I set MAKEFILE_4_GEM and MRUBY_ROOT environment variables, and try to install examples in doc/mrbgems. When I put the path of thems into GEMS.active, what i should do for another ? do i forget to do anything other ?

I want to know how to build and try my mruby extensions (mruby-uv / mruby-http )

@bovi

Hi @mattn,

at the moment it is only a compilable archive. I think the easiest way is to try to compile the examples. For that you do the following things:

  • change DISABLE_GEMS to ENABLE_GEMS in file include/mrbconf.h
  • change ENABLE_GEMS = false to ENABLE_GEMS = true in Makefile
  • add the absolute path to mrbgems/GEMS.active (i.e. absolute path to doc/mrbgems/c_extension_example)

Afterwards you just call make and make test. Tell me if something is unclear.

@mattn

Thank you for kindness. Then, when someone want to create new mrbgems,

  1. set MRUBY_ROOT / MAKEFILE_4_GEM environment variables.
  2. create working directory.
  3. type generate makefile . > Makefile.
  4. add code.
  5. type make on working directory.
  6. add absolute path into mrbgems/GEMS.active
  7. fix include/mrbconf.h as your said.
  8. fix $MRUBY_ROOT/Makefile as your said.
  9. type make && make test on $MRUBY_ROOT

After doing above, bin/mruby should enable my extension.

Is this ok ?

@bovi

Some parts are not necessary:

  • you don't call generate. this will be done by the build process automatically
  • you don't need to call make in your GEM directory

Do you have a GitHub repository you want to convert? Then I have a look at it and create a pull request as an example. Ok?

@mattn

Then I have a look at it and create a pull request as an example. Ok?

Coooooooooooooooooooooooooooooooooooooooooool!
Currently, I have three mruby extensions.

Probably, mruby-md5 is easily to convert. :)

@bovi bovi referenced this pull request in mattn/mruby-md5
Merged

MD5 gemified #1

@bovi

Hi @mattn,

I send you a pull request for the MD5 one (mattn/mruby-md5#1). I actually found an interesting flaw in mrbgems. Your lib name has a dash "mruby-md5". Due to the reason that mrbgems is using the name for a C function it will fail. So you have to change for now the dash to an underline. I will fix this particular issue soon. It shouldn't be hard but it points in an important direction where I should add more safety checks. Have a try if you can include this md5 gem. I added two test cases. If anything is still not working for you tell me.

@mattn

Thank you!

@beoran

OK, now I can start my work to port this to the CMake build system also. Might take me a while though...

@masuidrive

Hi @bovi, I have some questions.

I'm porting my "mruby-cfunc" library. it refer from mruby-cocoa, so mruby-cfunc has exported header files.
https://github.com/mobiruby/mruby-cfunc
Could you add all mrbgems exported header directory to CFLAGS in mrbgems?

And, What's order of calling each gems init method?
Is it same as GEMS.active lines?

Last one, GEMS.active path is absolute now, Could you change to relative from mrbgems/ when the path is relative?

@bovi

Hi @masuidrive,

  • gem init method will be called in the order of the GEMS.active line
  • about the exported header files, do you mean you want to get inside of your CFLAS something like "-I..path/to/every/gems/include"?
  • I will have a look at how to make the path relative in case it isn't absolute. but I would prefer to make it relative from mrbgems/g. That is the directory I consider to be the default directory for GEMs delivered by mruby directly.

Is this ok for you?

@masuidrive

Hi @bovi , thank you for replying.

  • I understood GEMs init order.
  • So it is. I want add all include directory of GEMs to CFLAGS.
  • I understood.

Could you add all-headers-include-feture? I hope,to support it.

@bovi

Hi @masuidrive,

I implemented:

  • relative/absolute path support in GEMS.active
  • include path integration into make calls
  • remove dependency of ENABLE_GEMS and only use DISABLE_GEMS as all the other flags

I couldn't test it on windows. there is one dependency which might work different under WIN32. I implemented a check but due to the lack of windows I couldn't test this edge case. I hope someone has a system to test it and report if it fails or not.

@sogabe

Thank you so much! In our case, it is good that mrbgems have a ability to link 'simple_http' to 'socket'. I think it is not necessary to have a central repository. mrubygems.org and gem command for mruby (not yet) can achieve our requirements :)

@schmurfy

A simple "list" repository like homebrew for mac os x would be nice to keep track of the available gems, even a wiki page would be enough if kept up to date.
Since mruby is more targeted at embedded or light devices I really wonder if a gem command would be of any use considering you have to recompile everything anyway, mruby is quite different from MRI.

I was curious if anyone was working on a socket gem ? I am really looking forward to try connecting mruby to the external world !

@Qard
@schmurfy

Thanks for the mruby-uv pointer but the code is not yet gemified I think, anyway I was thinking more about a low level socket extension.

@mattn

I'm author of mruby-uv.

Currently, we can't specify LDFLAGS for external library for mrbgems yet.

@Qard
@masuidrive

I'm working for LDFLAGS for mrbgems
plz wait a minute.

@mattn

@masuidrive probably, you are saying we can, but we need to specify for make command ? i've done already to build mruby-uv with my LDFLAGS from command-line. i'm thinking that mrbgems should be easy to build for all gem uesrs.

@masuidrive

It mean "You can set CFLAGS/LDFLAGS each GEM in gem's Makefile"

If you want to link with libuv, I can write "MRUBY_LDFLAGS = -luv" in gem's Makefile.

@mattn

Is it better ot use MRUBY_LDFLAGS+=-luv. It breaks mruby's behavior probably ?
BTW, I hope to do make test on my gem working directory.

@tsahara-iij

I'll try to convert some extension modules in our repository https://github.com/iij/mruby to mrbgems.
Thanks for great job, @bovi.

@bovi

@mattn what is your desire for make test? At the moment all your tests are automatically integrated into the normal mruby build process as long as your put them into a test directory of your GEM. Calling make test directly inside of your GEM project doesn't work with the current design due to the reason that it first needs to integrate your library into the mrbtest binary. Or did I misunderstood you in some way?

@tsahara-iij I'm looking forward to the IIJ extensions :)

@mattn

@bovi I'm doing all of things on the gem's working directory. I hope to run make test on the working directory. But not MUST, it's BETTER.

@bovi

@mattn ah ok I think I understand. You want to build mruby together with GEMs outside of the mruby source directory? I think this should be much cleaner and I don't see why we shouldn't be able to cleanup all Makefiles to make this work. Or did I misunderstand?

@mattn

You want to build mruby together with GEMs outside of the mruby source directory?

Yep! :)

why we shouldn't be able to cleanup all Makefiles to make this work.

Currently, we should open two terminals to build all.

@mattn

@bovi @masuidrive What I want to say is that we need to specify CFLAGS/LDFLAGS for bin/mruby not for each mrbgems on windows. Task of bin/mruby should include flags which is same flags which is used for mrbgems.

@mattn

And one more thing, on windows, order of -l flags must be resolvable. This mean, if libA.a uses functions in libB.a, we must specify the arguments as -lB -lA not -lA -lB.

@kristoph

@bovi You mentioned in an earlier comment that the GEM.active file can be located anywhere. How do I specify it's location when building mruby as a whole? Also, I understand GEM.active needs the full path of the GEM which is a little impractical when working on a team with multiple developers, any suggestions on how to address that? Thanks.

@schmurfy

just found the https://github.com/matsumoto-r/build_my_mruby repository and it confirmed what I first thought: I had no idea how many "gems" were already available out there !
Maybe a wiki page would be appropriate to keep track of them and avoid rebuilding the wheel, while I think the infrastructure rubygems have for MRI is a complete overkill in this case a way to keep track the gems would still be great.

@bovi

@kristoph it is possible to use an relative path from mrbgems/g it is possible to define the GEMS.active location inside of the Makefile. But @masuidrive is currently rewriting the
build process and by doing that some things will be relocated. So stay tuned. Most things woll become quite easy by next year.

@schmurfy I'm currently working on an application which contains a list of all Gems and which also provides a way to add your own one to it.

@schmurfy

@bovi great !

@schmurfy

@bovi just had a look at mgem, I was wondering how you plan to distribute it, it might make sense to distribute it as a rubygems (a real one ;) )

@bovi

@schmurfy the idea is to make a GEM indeed out of it ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 13, 2012
  1. @bovi
  2. @bovi
  3. @bovi
  4. @bovi

    make mrbc aware of the gem init

    bovi authored
  5. @bovi
  6. @bovi

    Add TODOs to finalize gems

    bovi authored
Commits on Sep 15, 2012
  1. @bovi

    Small modifications for location

    bovi authored
  2. @bovi

    Relocated md5 source

    bovi authored
  3. @bovi

    Remove old location of md5 source

    bovi authored
Commits on Sep 17, 2012
  1. @bovi

    Relocate files

    bovi authored
Commits on Sep 18, 2012
  1. @bovi
  2. @bovi

    remove second gem

    bovi authored
Commits on Sep 19, 2012
  1. @bovi
  2. @bovi
  3. @bovi

    Ignore generated files

    bovi authored
  4. @bovi

    Modify information messages

    bovi authored
  5. @bovi

    add hello world test program

    bovi authored
  6. @bovi

    Add default makefile for Gems

    bovi authored
  7. @bovi

    Integrate tests into mrbgems

    bovi authored
  8. @bovi
Commits on Sep 20, 2012
  1. @bovi
  2. @bovi

    Optimize Makefile

    bovi authored
Commits on Sep 21, 2012
  1. @bovi
  2. @bovi
  3. @bovi

    Modify README for examples

    bovi authored
  4. @bovi

    Rename Gem Examples

    bovi authored
  5. @bovi
  6. @bovi

    Optimize Makefiles

    bovi authored
  7. @bovi

    Fix Makefile

    bovi authored
  8. @bovi

    Another fix for Makefile

    bovi authored
Commits on Sep 22, 2012
  1. @bovi

    Catch some corner cases

    bovi authored
Commits on Sep 23, 2012
  1. @bovi

    Modify generator for using printf

    bovi authored
  2. @bovi

    Beautify generator

    bovi authored
  3. @bovi

    Empty GEM directory

    bovi authored
  4. @bovi

    Ignore gitignore

    bovi authored
  5. @bovi
  6. @bovi

    Remove gem_empty

    bovi authored
  7. @bovi
  8. @bovi

    Improve Gem Readme file

    bovi authored
  9. @bovi

    Improve Gem Readme Source

    bovi authored
  10. @bovi
  11. @bovi

    Spell fix in mrbgems Readme

    bovi authored
  12. @bovi

    Add location of gem to readme

    bovi authored
  13. @bovi
  14. @bovi

    Fix for not existing tests

    bovi authored
  15. @bovi

    Add accidently removed comment

    bovi authored
  16. @bovi
  17. @bovi

    Ignore built files of gem

    bovi authored
Commits on Sep 27, 2012
  1. @bovi
Commits on Nov 1, 2012
  1. Merge remote-tracking branch 'upstream/master' into mrbgems

    Daniel Bovensiepen authored
Commits on Nov 8, 2012
  1. @bovi

    Merge new change

    bovi authored
  2. @bovi

    Fix merge

    bovi authored
Commits on Nov 9, 2012
  1. @bovi
Commits on Nov 17, 2012
  1. @bovi
Commits on Nov 19, 2012
  1. @bovi
Commits on Nov 20, 2012
  1. @bovi

    Modify comments for generator

    bovi authored
Commits on Nov 21, 2012
  1. @bovi
  2. @bovi

    Modify C Extension

    bovi authored
  3. @bovi

    Modify Ruby Extension

    bovi authored
  4. @bovi
  5. @bovi
  6. @bovi
  7. @bovi
  8. @bovi
  9. @bovi
  10. @bovi
Commits on Nov 22, 2012
  1. @bovi
  2. @bovi
  3. @bovi
  4. @bovi

    Rename GEM init file

    bovi authored
  5. @bovi

    Clean GEM Generator a bit more

    bovi authored
  6. @bovi
  7. @bovi
  8. @bovi
  9. @bovi
  10. @bovi
  11. @bovi
  12. @bovi
  13. @bovi

    Improve README

    bovi authored
  14. @bovi
  15. @bovi
  16. @bovi
  17. @bovi
  18. @bovi
  19. @bovi
  20. @bovi
Commits on Nov 23, 2012
  1. @bovi

    Add ACTIVE_GEMS flag to Makefile

    bovi authored
  2. @bovi
  3. @bovi

    Respect dynamic GEMS.active file

    bovi authored
  4. @bovi
  5. @bovi
  6. @bovi
  7. @bovi
  8. @bovi

    Add the usage of MRUBY_ROOT to the mrbgems build system, so that we c…

    bovi authored
    …an easily build everywhere
  9. @bovi
Commits on Nov 24, 2012
  1. @bovi
Commits on Nov 26, 2012
  1. @bovi
  2. @bovi
Commits on Nov 27, 2012
  1. @bovi
Commits on Nov 28, 2012
  1. @bovi
Commits on Dec 1, 2012
  1. @bovi
Commits on Dec 4, 2012
  1. @bovi
Commits on Dec 5, 2012
  1. @bovi
Commits on Dec 6, 2012
  1. @bovi
Commits on Dec 7, 2012
  1. @bovi
  2. @bovi
This page is out of date. Refresh to see the latest.
Showing with 982 additions and 13 deletions.
  1. +6 −0 .gitignore
  2. +23 −3 Makefile
  3. +179 −0 doc/mrbgems/README.md
  4. +12 −0 doc/mrbgems/c_and_ruby_extension_example/Makefile
  5. +4 −0 doc/mrbgems/c_and_ruby_extension_example/README.md
  6. +5 −0 doc/mrbgems/c_and_ruby_extension_example/mrblib/example.rb
  7. +17 −0 doc/mrbgems/c_and_ruby_extension_example/src/example.c
  8. +7 −0 doc/mrbgems/c_and_ruby_extension_example/test/example.rb
  9. +10 −0 doc/mrbgems/c_extension_example/Makefile
  10. +4 −0 doc/mrbgems/c_extension_example/README.md
  11. +17 −0 doc/mrbgems/c_extension_example/src/example.c
  12. +3 −0  doc/mrbgems/c_extension_example/test/example.rb
  13. +9 −0 doc/mrbgems/ruby_extension_example/Makefile
  14. +4 −0 doc/mrbgems/ruby_extension_example/README.md
  15. +5 −0 doc/mrbgems/ruby_extension_example/mrblib/example.rb
  16. +3 −0  doc/mrbgems/ruby_extension_example/test/example.rb
  17. +1 −0  include/mrbconf.h
  18. 0  mrbgems/GEMS.active
  19. +76 −0 mrbgems/Makefile
  20. +91 −0 mrbgems/Makefile4gem
  21. +1 −0  mrbgems/g/.gitignore
  22. +420 −0 mrbgems/generator.c
  23. +4 −1 src/init.c
  24. +29 −4 test/Makefile
  25. +4 −0 test/init_mrbtest.c
  26. +19 −1 tools/mirb/Makefile
  27. +7 −0 tools/mrbc/mrbc.c
  28. +22 −4 tools/mruby/Makefile
View
6 .gitignore
@@ -25,3 +25,9 @@ cscope.out
/test/mrubytest.*
CMakeFiles
CMakeCache.txt
+/mrbgems/generator
+/mrbgems/gem_init.c
+/mrbgems/g/Makefile
+/mrbgems/g/MakefileGemList
+/mrbgems/g/mrbgemtest.ctmp
+/mrbgems/g/mrbgemtest.rbtmp
View
26 Makefile
@@ -7,6 +7,18 @@ export LL = gcc
export AR = ar
export YACC = bison
+MRUBY_ROOT := $(realpath .)
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+endif
+
ifeq ($(strip $(COMPILE_MODE)),)
# default compile option
COMPILE_MODE = debug
@@ -22,9 +34,9 @@ endif
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
- MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)'
+ MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)' ENABLE_GEMS='$(ENABLE_GEMS)' ACTIVE_GEMS='$(ACTIVE_GEMS)' MRUBY_ROOT='$(MRUBY_ROOT)'
else
- MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)'
+ MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)' ENABLE_GEMS='$(ENABLE_GEMS)' ACTIVE_GEMS='$(ACTIVE_GEMS)' MRUBY_ROOT='$(MRUBY_ROOT)'
endif
##############################
@@ -44,7 +56,11 @@ export CAT := cat
all :
@$(MAKE) -C src $(MAKE_FLAGS)
@$(MAKE) -C mrblib $(MAKE_FLAGS)
- @$(MAKE) -C tools/mruby $(MAKE_FLAGS)
+ifeq ($(ENABLE_GEMS),true)
+ @echo "-- MAKE mrbgems --"
+ @$(MAKE) -C mrbgems $(MAKE_FLAGS)
+endif
+ $(MAKE) -C tools/mruby $(MAKE_FLAGS)
@$(MAKE) -C tools/mirb $(MAKE_FLAGS)
# mruby test
@@ -56,6 +72,10 @@ test : all
.PHONY : clean
clean :
@$(MAKE) clean -C src $(MAKE_FLAGS)
+ifeq ($(ENABLE_GEMS),true)
+ @echo "-- CLEAN mrbgems --"
+ @$(MAKE) clean -C mrbgems $(MAKE_FLAGS)
+endif
@$(MAKE) clean -C tools/mruby $(MAKE_FLAGS)
@$(MAKE) clean -C tools/mirb $(MAKE_FLAGS)
@$(MAKE) clean -C test $(MAKE_FLAGS)
View
179 doc/mrbgems/README.md
@@ -0,0 +1,179 @@
+# mrbgems
+
+mrbgems is a library manager to integrate C and Ruby extension in an easy and
+standardised way into mruby.
+
+## Usage
+
+By default mrbgems is currently deactivated. As long as mrbgems is deactivated
+there is no overhead inside of the mruby interpreter.
+
+To activate you have to make the following changes:
+* set *ENABLE_GEMS* to *true* in *$(MRUBY_ROOT)/Makefile*
+* define *ENABLE_GEMS* in *$(MRUBY_ROOT)/include/mrbconf.h*
+* activate GEMs in *$(MRUBY_ROOT)/mrbgems/GEMS.active*
+
+Every activated GEM has to be listed with his absolute path in *GEMS.active*. It
+is possible to point to an alternative activate file:
+* set *ACTIVE_GEMS* to your customized GEM list in *$(MRUBY_ROOT)/Makefile*
+
+## GEM Structure
+
+The maximal GEM structure looks like this:
+
+```
++- GEM_NAME <- Name of GEM
+ |
+ +- mrblib/ <- Source for Ruby extension
+ |
+ +- src/ <- Source for C extension
+ |
+ +- test/ <- Test code (Ruby)
+ |
+ +- Makefile <- Makefile for GEM
+ |
+ +- README.md <- Readme for GEM
+```
+
+The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
+contains C files to extend mruby. The folder *test* contains pure Ruby files
+for testing purposes which will be used by *mrbtest*. The *Makefile* contains
+rules to build a *gem.a* file inside of the GEM directory. Which will be used
+for integration into the normal mruby build process. *README.md* is a short
+description of your GEM.
+
+## Build process
+
+mrbgems will call *make* to build and *make clean* to clean your GEM. You
+have to build a *mrb-GEMNAME-gem.a* file during this build process. How you
+are going to do this is up to you.
+
+To make your build process more easier and more standardized we suggest
+to include *mrbgems/Makefile4gem* which defines some helper rules. In
+case you include this Makefile you have to define specific pre-defined
+rules like *gem-all* for the build process and *gem-clean* for the clean
+process. There are additional helper rules for specific GEM examples
+below.
+
+## C Extension
+
+mruby can be extended with C. It is possible by using the C API to
+integrate C libraries into mruby.
+
+The *Makefile* is used for building a C extension. You should
+define *GEM* (GEM name), *GEM_C_FILES* (all C files) and
+*GEM_OBJECTS* (all Object files). Pay also attention that your
+*Makefile* has to build the object files. You can use
+*gem-c-files* to build a *mrb-GEMNAME-gem.a* out of your
+Object code and use *gem-clean-c-files* to clean the object files.
+
+### Pre-Conditions
+
+mrbgems expects that you have implemented a C method called
+*mrb_YOURGEMNAME_gem_init(mrb_state)*. YOURGEMNAME will be replaced
+by the name of you GEM. The directory name of your GEM is considered also
+as the name! If you call your GEM directory *c_extension_example*, your
+initialisation method could look like this:
+
+```
+void
+mrb_c_extension_example_gem_init(mrb_state* mrb) {
+ _class_cextension = mrb_define_module(mrb, "CExtension");
+ mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE());
+}
+```
+
+mrbgems will also use the *gem-clean* make target to clean up your GEM. Implement
+this target with the necessary rules!
+
+### Example
+
+```
++- c_extension_example/
+ |
+ +- src/
+ | |
+ | +- example.c <- C extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for C extension
+ |
+ +- Makefile <- Build rules for C extension
+ |
+ +- README.md
+```
+
+## Ruby Extension
+
+mruby can be extended with pure Ruby. It is possible to override existing
+classes or add new ones in this way. Put all Ruby files into the *mrblib*
+folder.
+
+The *Makefile* is used for building a Ruby extension. You should define
+*GEM* (GEM name) and *GEM_RB_FILES* (all Ruby files). You can use
+*gem-rb-files* to build a *mrb-GEMNAME-gem.a* out of your Ruby code and use
+*gem-clean-rb-files* to clean the generated C files.
+
+### Pre-Conditions
+
+mrbgems will automatically call the *gem-all* make target of your GEM.
+
+mrbgems will also use the *gem-clean* make target to clean up your GEM. Implement
+this target with the necessary rules!
+
+### Example
+
+```
++- ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for Ruby extension
+ |
+ +- Makefile
+ |
+ +- README.md
+```
+
+## C and Ruby Extension
+
+mruby can be extended with C and Ruby at the same time. It is possible to
+override existing classes or add new ones in this way. Put all Ruby files
+into the *mrblib* folder and all C files into the *src* folder.
+
+The *Makefile* is used for building a C and Ruby extension. You should
+define *GEM* (GEM name), *GEM_C_FILES* (all C files), *GEM_OBJECTS*
+(all Object files) and *GEM_RB_FILES* (all Ruby files). You can use
+*gem-c-and-rb-files* to build a *mrb-GEMNAME-gem.a* out of your Object
+and Ruby code. Use *gem-clean-c-and-rb-files* to clean the generated
+C files.
+
+### Pre-Conditions
+
+See C and Ruby example.
+
+### Example
+
+```
++- c_and_ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- src/
+ | |
+ | +- example.c <- C extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for C and Ruby extension
+ |
+ +- Makefile
+ |
+ +- README.md
View
12 doc/mrbgems/c_and_ruby_extension_example/Makefile
@@ -0,0 +1,12 @@
+GEM := c_and_ruby_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c)
+GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES))
+
+GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb)
+
+gem-all : $(GEM_OBJECTS) gem-c-and-rb-files
+
+gem-clean : gem-clean-c-and-rb-files
View
4 doc/mrbgems/c_and_ruby_extension_example/README.md
@@ -0,0 +1,4 @@
+C and Ruby Extension Example
+=========
+
+This is an example gem which implements a C and Ruby extension.
View
5 doc/mrbgems/c_and_ruby_extension_example/mrblib/example.rb
@@ -0,0 +1,5 @@
+class RubyExtension
+ def CRubyExtension.ruby_method
+ puts "A Ruby Extension"
+ end
+end
View
17 doc/mrbgems/c_and_ruby_extension_example/src/example.c
@@ -0,0 +1,17 @@
+#include <mruby.h>
+#include <stdio.h>
+
+static struct RClass *_class_cextension;
+
+static mrb_value
+mrb_c_method(mrb_state *mrb, mrb_value self)
+{
+ puts("A C Extension");
+ return self;
+}
+
+void
+mrb_c_and_ruby_extension_example_gem_init(mrb_state* mrb) {
+ _class_cextension = mrb_define_module(mrb, "CRubyExtension");
+ mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE());
+}
View
7 doc/mrbgems/c_and_ruby_extension_example/test/example.rb
@@ -0,0 +1,7 @@
+assert('C and Ruby Extension Example 1') do
+ CRubyExtension.respond_to? :c_method
+end
+
+assert('C and Ruby Extension Example 2') do
+ CRubyExtension.respond_to? :ruby_method
+end
View
10 doc/mrbgems/c_extension_example/Makefile
@@ -0,0 +1,10 @@
+GEM := c_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c)
+GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES))
+
+gem-all : $(GEM_OBJECTS) gem-c-files
+
+gem-clean : gem-clean-c-files
View
4 doc/mrbgems/c_extension_example/README.md
@@ -0,0 +1,4 @@
+C Extension Example
+=========
+
+This is an example gem which implements a C extension.
View
17 doc/mrbgems/c_extension_example/src/example.c
@@ -0,0 +1,17 @@
+#include <mruby.h>
+#include <stdio.h>
+
+static struct RClass *_class_cextension;
+
+static mrb_value
+mrb_c_method(mrb_state *mrb, mrb_value self)
+{
+ puts("A C Extension");
+ return self;
+}
+
+void
+mrb_c_extension_example_gem_init(mrb_state* mrb) {
+ _class_cextension = mrb_define_module(mrb, "CExtension");
+ mrb_define_class_method(mrb, _class_cextension, "c_method", mrb_c_method, ARGS_NONE());
+}
View
3  doc/mrbgems/c_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('C Extension Example') do
+ CExtension.respond_to? :c_method
+end
View
9 doc/mrbgems/ruby_extension_example/Makefile
@@ -0,0 +1,9 @@
+GEM := ruby_extension_example
+
+include $(MAKEFILE_4_GEM)
+
+GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb)
+
+gem-all : gem-rb-files
+
+gem-clean : gem-clean-rb-files
View
4 doc/mrbgems/ruby_extension_example/README.md
@@ -0,0 +1,4 @@
+Pure Ruby Extension Example
+=========
+
+This is an example gem which implements a pure Ruby extension.
View
5 doc/mrbgems/ruby_extension_example/mrblib/example.rb
@@ -0,0 +1,5 @@
+class RubyExtension
+ def RubyExtension.ruby_method
+ puts "A Ruby Extension"
+ end
+end
View
3  doc/mrbgems/ruby_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('Ruby Extension Example') do
+ RubyExtension.respond_to? :ruby_method
+end
View
1  include/mrbconf.h
@@ -50,6 +50,7 @@
//#define DISABLE_TIME /* Time class */
//#define DISABLE_STRUCT /* Struct class */
//#define DISABLE_STDIO /* use of stdio */
+#define DISABLE_GEMS /* Package Manager mrbgems */
#undef HAVE_UNISTD_H /* WINDOWS */
#define HAVE_UNISTD_H /* LINUX */
View
0  mrbgems/GEMS.active
No changes.
View
76 mrbgems/Makefile
@@ -0,0 +1,76 @@
+# makefile description.
+# add gems to the ruby library
+
+ifeq ($(strip $(MRUBY_ROOT)),)
+ MRUBY_ROOT := $(realpath ..)
+endif
+
+LIBR := ../lib/libmruby.a
+RM_F := rm -f
+CC_FLAGS := -Wall -Werror-implicit-function-declaration -g -O3 -MMD -I. -I./../include
+
+export CC = gcc
+export LL = gcc
+export AR = ar
+
+GENERATOR := $(MRUBY_ROOT)/mrbgems/generator
+ifeq ($(OS),Windows_NT)
+ GENERATOR_BIN := $(GENERATOR).exe
+else
+ GENERATOR_BIN := $(GENERATOR)
+endif
+GEM_INIT := gem_init
+GEM_MAKEFILE := g/Makefile
+GEM_MAKEFILE_LIST := g/MakefileGemList
+GEMDLIB := g/mrbgemtest.ctmp
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+endif
+
+##############################
+# generic build targets, rules
+
+.PHONY : all
+all : all_gems $(GEM_INIT).a
+
+$(GEM_INIT).a : $(GEM_INIT).o
+ $(AR) rs gem_init.a $(GEM_INIT).o
+
+all_gems : $(GENERATOR_BIN)
+ @echo "Generate Gem List Makefile"
+ $(GENERATOR_BIN) makefile_list "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE_LIST)
+ @echo "Generate Gem Makefile"
+ $(GENERATOR_BIN) makefile "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE)
+ @echo "Build all gems"
+ $(MAKE) -C g MRUBY_ROOT='$(MRUBY_ROOT)' ACTIVE_GEMS="$(ACTIVE_GEMS)"
+
+$(GEM_INIT).c : $(GENERATOR_BIN)
+ @echo "Generate Gem driver"
+ $(GENERATOR_BIN) $(GEM_INIT) "$(ACTIVE_GEMS)" > $@
+
+$(GEM_INIT).o : $(GEM_INIT).c
+ @echo "Build the driver which initializes all gems"
+ $(CC) $(CC_FLAGS) -MMD -c $< -o $@
+
+# Generator
+
+$(GENERATOR_BIN) : $(GENERATOR).o
+ @echo "Build the generator which creates the driver and Gem Makefile"
+ $(LL) -o $@ $(CC_FLAGS) $<
+
+$(GENERATOR).o : $(GENERATOR).c
+ $(CC) $(CC_FLAGS) -MMD -c $< -o $@
+
+.PHONY : prepare-test
+prepare-test :
+ @$(MAKE) prepare-test -C g ACTIVE_GEMS="$(ACTIVE_GEMS)" MRUBY_ROOT='$(MRUBY_ROOT)'
+
+# clean driver and all gems
+.PHONY : clean
+clean : $(GENERATOR_BIN)
+ @echo "Cleanup Gems"
+ $(GENERATOR_BIN) makefile "$(ACTIVE_GEMS)" > $(GEM_MAKEFILE)
+ $(MAKE) clean -C g ACTIVE_GEMS="$(ACTIVE_GEMS)" MRUBY_ROOT='$(MRUBY_ROOT)'
+ -$(RM_F) $(GEM_INIT).c *.o *.d $(GENERATOR_BIN) $(GEM_MAKEFILE) $(GEM_MAKEFILE_LIST) gem_init.a
View
91 mrbgems/Makefile4gem
@@ -0,0 +1,91 @@
+# This is the default Makefile integrated
+# by each Gem. It integrates important constants
+# for usage inside of a Gem.
+
+ifeq ($(strip $(MRUBY_ROOT)),)
+ # mruby src root
+ MRUBY_ROOT := $(realpath ../../..)
+endif
+
+# Tools
+CC := gcc
+RM := rm -f
+AR := ar
+
+SRC_DIR := src
+MRB_DIR := mrblib
+
+INCLUDES := -I$(SRC_DIR) -I$(MRUBY_ROOT)/include -I$(MRUBY_ROOT)/src -I.
+CFLAGS := $(INCLUDES) -O3 -g -Wall -Werror-implicit-function-declaration
+
+# LIBR can be manipulated with command line arguments
+ifeq ($(strip $(LIBR)),)
+ # default mruby library
+ LIBR := $(MRUBY_ROOT)/lib/libmruby.a
+endif
+
+GEM_PACKAGE := mrb-$(GEM)-gem.a
+
+ifeq ($(strip $(ACTIVE_GEMS)),)
+ # the default file which contains the active GEMs
+ ACTIVE_GEMS = GEMS.active
+endif
+
+# Default rules which are calling the
+# gem specific gem-all and gem-clean
+# implementations of a gem
+
+.PHONY : all
+all : gem-info gem-all
+
+gem-info:
+ @echo "Building Gem '$(GEM)'"
+
+# Building target for C and Ruby files
+gem-c-and-rb-files : gem_mixlib.o
+ $(AR) rs $(GEM_PACKAGE) $(GEM_OBJECTS) $^
+
+gem_mixlib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp
+ cat $^ > $@
+
+gem_mixlib_init.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mixlib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+# Building target for C files
+gem-c-files : gem_srclib.o
+ $(AR) rs $(GEM_PACKAGE) $(GEM_OBJECTS) $<
+
+gem_srclib.c :
+ $(MRUBY_ROOT)/mrbgems/generator gem_srclib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+# Building target for Ruby Files
+gem-rb-files : gem_mrblib.o
+ $(AR) rs $(GEM_PACKAGE) $<
+
+gem_mrblib.c : gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mrblib_init.ctmp
+ cat $^ > $@
+
+gem_mrblib_header.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mrblib "$(ACTIVE_GEMS)" > $@
+
+gem_mrblib_init.ctmp :
+ $(MRUBY_ROOT)/mrbgems/generator gem_mrblib $(GEM) "$(ACTIVE_GEMS)" > $@
+
+gem_mrblib_irep.ctmp : gem_mrblib.rbtmp
+ $(MRUBY_ROOT)/bin/mrbc -Bgem_mrblib_irep_$(GEM) -o$@ $<
+
+gem_mrblib.rbtmp :
+ cat $(GEM_RB_FILES) > $@
+
+gem-clean-c-and-rb-files :
+ -$(RM) $(GEM_PACKAGE) gem_mixlib.o gem_mixlib.c gem_mrblib_header.ctmp gem_mrblib_irep.ctmp gem_mixlib_init.ctmp gem_mrblib.rbtmp
+
+gem-clean-c-files :
+ -$(RM) $(GEM_PACKAGE) gem_srclib.c gem_srclib.o $(GEM_OBJECTS)
+
+gem-clean-rb-files :
+ -$(RM) $(GEM_PACKAGE) gem_mrblib.o gem_mrblib.c gem_mrblib_header.ctmp gem_mrblib_init.ctmp gem_mrblib_irep.ctmp gem_mrblib.rbtmp
+
+.PHONY : clean
+clean : gem-clean
+ @echo "Gem '$(GEM)' is clean"
View
1  mrbgems/g/.gitignore
@@ -0,0 +1 @@
+!.gitignore
View
420 mrbgems/generator.c
@@ -0,0 +1,420 @@
+/*
+** generator.c - Generator for mrbgems
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mrbconf.h>
+
+/*
+ * Get the file name part of *path*
+ *
+ * Arguments:
+ * path:
+ * String which represents the path
+ *
+ */
+static char
+*get_file_name(char *path)
+{
+ char *base = strrchr(path, '/');
+ return base ? base+1 : path;
+}
+
+/*
+ * Search in *s* for *old* and replace with *new*.
+ *
+ * Arguments:
+ * s:
+ * String in which the the replacement will be done
+ * old:
+ * String which will be replaced
+ * new:
+ * String which will be the replacement
+ *
+ */
+static char
+*replace(const char *s, const char *old, const char *new)
+{
+ char *ret;
+ int i, count = 0;
+ size_t newlen = strlen(new);
+ size_t oldlen = strlen(old);
+
+ for (i = 0; s[i] != '\0'; i++) {
+ if (strstr(&s[i], old) == &s[i]) {
+ count++;
+ i += oldlen - 1;
+ }
+ }
+
+ ret = malloc(i + count * (newlen - oldlen));
+ if (ret == NULL)
+ exit(EXIT_FAILURE);
+
+ i = 0;
+ while (*s) {
+ if (strstr(s, old) == s) {
+ strcpy(&ret[i], new);
+ i += newlen;
+ s += oldlen;
+ }
+ else
+ ret[i++] = *s++;
+ }
+ ret[i] = '\0';
+
+ return ret;
+}
+
+/*
+ * Template generator for each active GEM
+ *
+ * Arguments:
+ * before:
+ * String before each GEM template
+ * after:
+ * String after each GEM template
+ * start:
+ * String at the start of the template
+ * end:
+ * String at the end of the template
+ * full_path
+ * Should the full path of the GEM be used?
+ *
+ */
+static char*
+for_each_gem (char before[1024], char after[1024],
+ char start[1024], char end[1024],
+ int full_path, char active_gems[1024])
+{
+ /* active GEM check */
+ FILE *active_gem_file;
+ char gem_char;
+ char gem_name[1024] = { 0 };
+ int char_index;
+ char gem_list[1024][1024] = { { 0 }, { 0 } };
+ int gem_index;
+ int i;
+
+ /* return value */
+ char* complete_line = malloc(4096 + sizeof(char));
+ strcpy(complete_line, "");
+ strcat(complete_line, start);
+
+ /* Read out the active GEMs */
+ active_gem_file = fopen(active_gems, "r+");
+ if (active_gem_file != NULL) {
+ char_index = 0;
+ gem_index = 0;
+ while((gem_char = fgetc(active_gem_file)) != EOF) {
+ if (gem_char == '\n') {
+ /* Every line contains one active GEM */
+ gem_name[char_index++] = '\0';
+ strcpy(gem_list[gem_index++], gem_name);
+
+ gem_name[0] = '\0';
+ char_index = 0;
+ }
+ else
+ gem_name[char_index++] = gem_char;
+ }
+
+ fclose(active_gem_file);
+ }
+ else { /* Error: Active GEM list couldn't be loaded */ }
+
+ for(i = 0; i < gem_index; i++) {
+ strcat(complete_line, before);
+ if (full_path == TRUE)
+ strcat(complete_line, gem_list[i]);
+ else
+ strcat(complete_line, get_file_name(gem_list[i]));
+ strcat(complete_line, replace(after, "#GEMNAME#", get_file_name(gem_list[i])));
+ }
+
+ strcat(complete_line, end);
+ return complete_line;
+}
+
+/*
+ * Gem Makefile Generator
+ *
+ * Global Makefile which starts the build process
+ * for every active GEM.
+ *
+ */
+static void
+make_gem_makefile(char active_gems[1024])
+{
+ char *gem_check = { 0 };
+ int gem_empty;
+
+ printf("ifeq ($(strip $(MRUBY_ROOT)),)\n"
+ " MRUBY_ROOT := $(realpath ../../..)\n"
+ "endif\n\n"
+ "MAKEFILE_4_GEM := $(MRUBY_ROOT)/mrbgems/Makefile4gem\n\n"
+ "CFLAGS := -I. -I$(MRUBY_ROOT)/include -I$(MRUBY_ROOT)/src\n\n"
+ "ifeq ($(OS),Windows_NT)\n"
+ " MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)' MRUBY_ROOT='$(MRUBY_ROOT)' MAKEFILE_4_GEM='$(MAKEFILE_4_GEM)'\n"
+ "else\n"
+ " MAKE_FLAGS = --no-print-directory CC='$(CC)' LL='$(LL)' ALL_CFLAGS='$(ALL_CFLAGS)' MRUBY_ROOT='$(MRUBY_ROOT)' MAKEFILE_4_GEM='$(MAKEFILE_4_GEM)'\n"
+ "endif\n\n");
+
+ /* is there any GEM available? */
+ gem_check = for_each_gem("", "", "", "", TRUE, active_gems);
+ if (strcmp(gem_check, "") == 0)
+ gem_empty = TRUE;
+ else
+ gem_empty = FALSE;
+
+ /* Makefile Rules to build every single GEM */
+
+ printf(".PHONY : all\n");
+ if (gem_empty)
+ printf("all :\n\n");
+ else {
+ printf("all : all_gems\n\n");
+
+ /* Call make for every GEM */
+ printf("all_gems :\n%s\n",
+ for_each_gem("\t@$(MAKE) -C ", " $(MAKE_FLAGS)\n", "", "", TRUE, active_gems)
+ );
+ printf("\n");
+ }
+
+ /* Makefile Rules to Test GEMs */
+
+ printf(".PHONY : prepare-test\n"
+ "prepare-test :\n"
+ );
+ if (!gem_empty)
+ printf("%s",
+ for_each_gem(" ", "/test/*.rb ", "\tcat", " > mrbgemtest.rbtmp", TRUE, active_gems)
+ );
+ else
+ printf("\t$(MRUBY_ROOT)/mrbgems/generator rbtmp \"%s\"> mrbgemtest.rbtmp", active_gems);
+
+ printf("\n\t$(MRUBY_ROOT)/bin/mrbc -Bmrbgemtest_irep -omrbgemtest.ctmp mrbgemtest.rbtmp\n\n");
+
+ /* Makefile Rules to Clean GEMs */
+
+ printf(".PHONY : clean\n"
+ "clean :\n"
+ "\t$(RM) *.c *.d *.rbtmp *.ctmp *.o mrbtest\n");
+ if (!gem_empty)
+ printf("%s",
+ for_each_gem("\t@$(MAKE) clean -C ", " $(MAKE_FLAGS)\n", "", "", TRUE, active_gems)
+ );
+}
+
+/*
+ * Gem Makefile List Generator
+ *
+ * Creates a Makefile which will be included by other Makefiles
+ * which need to know which GEMs are active.
+ *
+ */
+static void
+make_gem_makefile_list(char active_gems[1024])
+{
+ printf("%s",
+ for_each_gem(" ", "/mrb-#GEMNAME#-gem.a", "GEM_LIST := ", "\n", TRUE, active_gems)
+ );
+
+ printf("GEM_ARCHIVE_FILES := $(MRUBY_ROOT)/mrbgems/gem_init.a\n"
+ "GEM_ARCHIVE_FILES += $(GEM_LIST)\n\n");
+}
+
+/*
+ * gem_init.c Generator
+ *
+ */
+static void
+make_gem_init(char active_gems[1024])
+{
+ printf("/*\n"
+ " * This file contains a list of all\n"
+ " * initializing methods which are\n"
+ " * necessary to bootstrap all gems.\n"
+ " *\n"
+ " * IMPORTANT:\n"
+ " * This file was generated!\n"
+ " * All manual changes will get lost.\n"
+ " */\n\n"
+ "#include \"mruby.h\"\n");
+
+ /* Protoype definition of all initialization methods */
+ printf("\n%s",
+ for_each_gem("void GENERATED_TMP_mrb_", "_gem_init(mrb_state*);\n", "", "", FALSE, active_gems)
+ );
+ printf("\n");
+
+ /* mrb_init_mrbgems(mrb) method for initialization of all GEMs */
+ printf("void\n"
+ "mrb_init_mrbgems(mrb_state *mrb) {\n");
+ printf( "%s",
+ for_each_gem(" GENERATED_TMP_mrb_", "_gem_init(mrb);\n", "", "", FALSE, active_gems)
+ );
+ printf("}");
+}
+
+/*
+ * Empty Generator
+ *
+ * Generates a clean file with one new line.
+ *
+ */
+static void
+make_rbtmp(char active_gems[1024])
+{
+ printf("\n");
+}
+
+/*
+ * Header Generator
+ *
+ * Head of the C Code for loading the GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_mrblib_header(char active_gems[1024])
+{
+ printf("/*\n"
+ " * This file is loading the irep\n"
+ " * Ruby GEM code.\n"
+ " *\n"
+ " * IMPORTANT:\n"
+ " * This file was generated!\n"
+ " * All manual changes will get lost.\n"
+ " */\n\n"
+ "#include \"mruby.h\"\n"
+ "#include \"mruby/irep.h\"\n"
+ "#include \"mruby/dump.h\"\n"
+ "#include \"mruby/string.h\"\n"
+ "#include \"mruby/proc.h\"\n\n");
+}
+
+/*
+ * mrblib Generator
+ *
+ * Generates the C Code for loading
+ * the pure Ruby GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_mrblib(char argv[1024], char active_gems[1024])
+{
+ printf("\n"
+ "void\n"
+ "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n"
+ " mrb_load_irep(mrb, gem_mrblib_irep_%s);\n"
+ " if (mrb->exc) {\n"
+ " mrb_p(mrb, mrb_obj_value(mrb->exc));\n"
+ " exit(0);\n"
+ " }\n"
+ "}", argv, argv);
+}
+
+/*
+ * srclib Generator
+ *
+ * Generates the C Code for loading
+ * the pure C GEMs into the interpreter.
+ *
+ */
+static void
+make_gem_srclib(char argv[1024], char active_gems[1024])
+{
+ printf("/*\n"
+ " * This file is loading the irep\n"
+ " * Ruby GEM code.\n"
+ " *\n"
+ " * IMPORTANT:\n"
+ " * This file was generated!\n"
+ " * All manual changes will get lost.\n"
+ " */\n\n"
+ "#include \"mruby.h\"\n");
+
+ printf("\n"
+ "void mrb_%s_gem_init(mrb_state*);\n", argv);
+
+ printf("\n"
+ "void\n"
+ "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n"
+ " mrb_%s_gem_init(mrb);\n"
+ "}", argv, argv);
+}
+
+/*
+ * mixlib Generator
+ *
+ * Generates the C Code for loading
+ * the mixed Ruby and C GEMs
+ * into the interpreter.
+ *
+ */
+static void
+make_gem_mixlib(char argv[1024], char active_gems[1024])
+{
+ printf("\n"
+ "void mrb_%s_gem_init(mrb_state*);\n", argv);
+
+ printf("\n"
+ "void\n"
+ "GENERATED_TMP_mrb_%s_gem_init(mrb_state *mrb) {\n"
+ " mrb_%s_gem_init(mrb);\n"
+ " mrb_load_irep(mrb, gem_mrblib_irep_%s);\n"
+ " if (mrb->exc) {\n"
+ " mrb_p(mrb, mrb_obj_value(mrb->exc));\n"
+ " exit(0);\n"
+ " }\n"
+ "}", argv, argv, argv);
+}
+
+/*
+ * Start the generator and decide what to generate.
+ *
+ */
+int
+main (int argc, char *argv[])
+{
+ const char * argument_info = "Wrong argument! Options: 'makefile', 'gem_init', 'rbtmp', 'gem_mrblib', gem_srclib\n";
+ if (argc == 3) {
+ if (strcmp(argv[1], "makefile") == 0)
+ make_gem_makefile(argv[2]);
+ else if (strcmp(argv[1], "makefile_list") == 0)
+ make_gem_makefile_list(argv[2]);
+ else if (strcmp(argv[1], "gem_init") == 0)
+ make_gem_init(argv[2]);
+ else if (strcmp(argv[1], "rbtmp") == 0)
+ make_rbtmp(argv[2]);
+ else if (strcmp(argv[1], "gem_mrblib") == 0)
+ make_gem_mrblib_header(argv[2]);
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+ }
+ else if (argc == 4) {
+ if (strcmp(argv[1], "gem_mrblib") == 0)
+ make_gem_mrblib(argv[2], argv[3]);
+ else if (strcmp(argv[1], "gem_srclib") == 0)
+ make_gem_srclib(argv[2], argv[3]);
+ else if (strcmp(argv[1], "gem_mixlib") == 0)
+ make_gem_mixlib(argv[2], argv[3]);
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+ }
+ else {
+ printf("%s", argument_info);
+ return 1;
+ }
+
+ return 0;
+}
View
5 src/init.c
@@ -27,6 +27,7 @@ void mrb_init_print(mrb_state*);
void mrb_init_time(mrb_state*);
void mrb_init_math(mrb_state*);
void mrb_init_mrblib(mrb_state*);
+void mrb_init_mrbgems(mrb_state*);
#define DONE mrb_gc_arena_restore(mrb, 0);
void
@@ -64,6 +65,8 @@ mrb_init_core(mrb_state *mrb)
#ifdef ENABLE_MATH
mrb_init_math(mrb); DONE;
#endif
-
mrb_init_mrblib(mrb); DONE;
+#ifdef ENABLE_GEMS
+ mrb_init_mrbgems(mrb); DONE;
+#endif
}
View
33 test/Makefile
@@ -3,9 +3,29 @@
# project-specific macros
# extension of the executable-file is modifiable(.exe .out ...)
+MRUBY_ROOT := ..
BASEDIR = .
TARGET := mrbtest
LIBR := ../lib/libmruby.a
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(ENABLE_GEMS),false)
+ GEM_ARCHIVE_FILES =
+else
+ GEMDIR := ../mrbgems
+ GEMDLIB := $(GEMDIR)/g/mrbgemtest.ctmp
+ MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList
+ ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),)
+ GEM_ARCHIVE_FILES =
+ else
+ include $(MAKEFILE_GEM_LIST)
+ endif
+endif
+
MLIB := $(TARGET).o
CLIB := $(TARGET).c
INIT := init_$(TARGET).c
@@ -58,7 +78,6 @@ MRUBY= ../bin/mruby
EXE := $(TARGET)
endif
-
##############################
# generic build targets, rules
@@ -76,7 +95,7 @@ all : $(EXE) $(MRUBY) $(TESTRB) $(TESTMRB)
# executable constructed using linker from object files
$(EXE) : $(OBJS) $(LIBR)
- $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(LIBS)
+ $(LL) -o $@ $(CFLAGS) $(OBJS) $(LIBR) $(GEM_ARCHIVE_FILES) $(LIBS)
-include $(OBJS:.o=.d)
@@ -85,8 +104,14 @@ $(OBJS) : %.o : %.c
$(CC) $(ALL_CFLAGS) -MMD $(INCLUDES) -c $< -o $@
# Compile C source from merged mruby source
-$(CLIB) : $(RLIB) $(MRBC) $(INIT)
- $(MRBC) -Bmrbtest_irep -o$(DLIB) $(RLIB); $(CAT) $(INIT) $(DLIB) > $@
+$(CLIB) : $(DLIB) $(INIT)
+ifeq ($(ENABLE_GEMS),true)
+ @$(MAKE) prepare-test -C $(GEMDIR)
+endif
+ $(CAT) $(INIT) $(DLIB) $(GEMDLIB) > $@
+
+$(DLIB) : $(RLIB) $(MRBC)
+ $(MRBC) -Bmrbtest_irep -o$@ $(RLIB)
# merge mruby sources
$(RLIB) : $(ASSLIB) $(MRBS)
View
4 test/init_mrbtest.c
@@ -5,11 +5,15 @@
#include "mruby/proc.h"
extern const char mrbtest_irep[];
+extern const char mrbgemtest_irep[];
void
mrb_init_mrbtest(mrb_state *mrb)
{
mrb_load_irep(mrb, mrbtest_irep);
+#ifdef ENABLE_GEMS
+ mrb_load_irep(mrb, mrbgemtest_irep);
+#endif
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
exit(0);
View
20 tools/mirb/Makefile
@@ -3,9 +3,27 @@
# project-specific macros
# extension of the executable-file is modifiable(.exe .out ...)
+MRUBY_ROOT := ../..
BASEDIR = ../../src
TARGET := ../../bin/mirb
LIBR := ../../lib/libmruby.a
+
+ifeq ($(strip $(ENABLE_GEMS)),)
+ # by default GEMs are deactivated
+ ENABLE_GEMS = false
+endif
+
+ifeq ($(ENABLE_GEMS),false)
+ GEM_ARCHIVE_FILES =
+else
+ MAKEFILE_GEM_LIST := $(MRUBY_ROOT)/mrbgems/g/MakefileGemList
+ ifeq ($(wildcard $(MAKEFILE_GEM_LIST)),)
+ GEM_ARCHIVE_FILES =
+ else
+ include $(MAKEFILE_GEM_LIST)
+ endif
+endif
+
ifeq ($(OS),Windows_NT)
EXE := $(