Forum: Ruby Compiling a Ruby app

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Sharagoz -. (Guest)
on 2009-03-02 16:15
Hi
Does there exist a compiler for compiling Ruby apps?
I dont like the idea of being forced to distribute apps open source.
My first concern is that distribution, at least on the windows platform,
will differ a lot from what users are used to.
My second concern is protecting source code.
I realize that everything that can be compiled can also be decompiled,
but I would like it to take a little more effort for average Joe to
view/edit source code than to simply right-click on somefile.rb and
opening it in wordpad.

I know about "rubyscript2exe", which solves the first part of the
problem, but not the second.

-S
Roger P. (Guest)
on 2009-03-02 20:55
Sharagoz -- wrote:
> Hi
> Does there exist a compiler for compiling Ruby apps?
I believe there is a way to do this through using jruby, though I've
never done it.
Cheers!
-=r
David M. (Guest)
on 2009-03-03 12:11
(Received via mailing list)
Sharagoz -- wrote:
> My second concern is protecting source code.
> I realize that everything that can be compiled can also be decompiled,
>

That is not entirely true. Or rather, it can be "decompiled", all right,
but not into anything resembling the original source code.

> but I would like it to take a little more effort for average Joe to
> view/edit source code than to simply right-click on somefile.rb and
> opening it in wordpad.

The main question you need to ask yourself is, why don't you want Joe to
do that?

If your goal is to prevent others from taking your code, repackaging it,
and selling it as their own, that's fine, although there are better ways
of doing it -- like legal measures.

If your goal is to prevent users from doing something they want to do --
for example, if this is a form of copy protection -- you should realize
two things:

 - Someone (not Average Joe) will reverse engineer it, and publish a
crack.
 - Average Joe will be able to find that crack.

That is true with or without source code. It's not a "might", it's a
"will".

But yes, if it's not possible now, I believe it will be possible to
compile JRuby.

But there is a reason the obvious solution is to never give your users a
program at all -- instead, build it as a web app, and host it yourself.
Sharagoz -. (Guest)
on 2009-03-03 12:50
Thanks for the input.

So there is no way to compile a "regular" ruby app, you'd have to go for
Jruby?
I've seen projects like "Brite", "YARV" and "Rubinius" mentioned that
seems to be "compiler related" projects. (Excuse the poor terminology).
Will any of those do the job?

Im not concerned about reverse engineering or cracks being made for my
software. All I want is to be able to distribute it the traditional way
like most commercial software is (at least on the windows platform).
Open source makes code stealing too easy.

I find it strange that there isnt a compiler readily available for Ruby.
Is there a technical reason why there shouldnt be one?
Is it because Ruby is ment to be pure open source and never used in the
commercial sector?

I use Ruby on Rails for web apps, and its an excelent framework to work
in.
Sometimes though, client apps are a better solution and I was hoping I
could use Ruby for that purpose because I've grown fond of Ruby through
RoR.
Rick D. (Guest)
on 2009-03-03 15:24
(Received via mailing list)
On Tue, Mar 3, 2009 at 5:09 AM, David M. <removed_email_address@domain.invalid>
wrote:

> Sharagoz -- wrote:
>
>> My second concern is protecting source code.
>> I realize that everything that can be compiled can also be decompiled,
>>
>>
>
> That is not entirely true. Or rather, it can be "decompiled", all right,
> but not into anything resembling the original source code.


Actually closer than you might think:

require 'rubygems'
require 'ruby2ruby'

class Foo
  def bar
    a = 1
    b = 2
    a + b
  end
end

puts Ruby2Ruby.translate(Foo)

produces:

class Foo < Object
  def bar
    a = 1
    b = 2
    (a + b)
  end
end

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Florian G. (Guest)
on 2009-03-03 15:37
(Received via mailing list)
On Mar 3, 2009, at 11:09 AM, David M. wrote:

> Sharagoz -- wrote:
>> My second concern is protecting source code.
>> I realize that everything that can be compiled can also be
>> decompiled,
>>
>
> That is not entirely true. Or rather, it can be "decompiled", all
> right, but not into anything resembling the original source code.


Almost every kind of Bytecode is surprisingly well decompilable.

BTW: Open Source has nothing to do with the code being viewable.
Battlefield 2 and Eve Online for example contain large portions of
viewable code, but none of it is open source.

If Bytecode is enough for you: A patched Ruby 1.9-Interpreter is able
of loading Bytecode (it is off, due to likely changes in the Bytecode
format). Exporting is already available. I don't think there are
readymade solutions available, but you could construct something out
of it.

Regards,
Florian

--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
John W. (Guest)
on 2009-03-03 15:54
(Received via mailing list)
On Tue, Mar 3, 2009 at 5:09 AM, David M. <removed_email_address@domain.invalid>
wrote:
>> view/edit source code than to simply right-click on somefile.rb and
>> opening it in wordpad.
>
> The main question you need to ask yourself is, why don't you want Joe to do
> that?
>
> If your goal is to prevent others from taking your code, repackaging it, and
> selling it as their own, that's fine, although there are better ways of
> doing it -- like legal measures.

You know, I see this argument repeated from time to time on the ruby
mailing list and I have to disagree. Legal measures are a (expensive)
way of defending your intellectual property, but preventing access is
the easiest and by far the cheapest. Any time you have to do something
with the word "legal" in it, it's costing you hourly money. For a
small shop, this can often be debilitating.

The only time legal measures would be pointed out as a better option
than prevention...is when the option for prevention doesn't exist...

John
Florian G. (Guest)
on 2009-03-03 17:23
(Received via mailing list)
On Mar 3, 2009, at 2:51 PM, John W. wrote:

>> right, but
>> If your goal is to prevent others from taking your code,
> small shop, this can often be debilitating.
>
> The only time legal measures would be pointed out as a better option
> than prevention...is when the option for prevention doesn't exist...
>
> John
>

My argument is usually a different one: is your code sufficiently
interesting and reusable enough to be stolen?

Usally, programs are stolen entirely, not in parts. No part of code
blurring can fix that.

There are solutions to this (code obfuscation, removing comments,
etc.) that make it harder for uninitated thieves, but a lot of people
just don't see a need for them. So, no one implements them. If you see
the need: go ahead.

It is a problem of introspective languages since day 1: if the program
knows everything about itself, everyone can make the program speak
about itself.

Regards,
Florian


--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
Kyle S. (Guest)
on 2009-03-03 18:04
(Received via mailing list)
Err, not to attempt to de-rail a good open vs closed argument, but
lets look at what the guy said,

"Im not concerned about reverse engineering or cracks being made for my
software. All I want is to be able to distribute it the traditional way
like most commercial software is"

It sounds to me like the main thing he wants to make a self contained
installer that bundles up everything needed for the app to run, so
it's transparent to the user whether it's ruby, C#, python or Java.

That's rather admirable, especially considering that even some
Microsoft downloads have dependencies that aren't auto-installed.

What are the ways do do that?  From hardest to easiest:
A) Have the installer check for a compatible ruby then install if
necessary (I used to make installers for work, this method may really
suck unless someone has already made a template, or the installer
software already supports it)
B) Install just enough of a ruby distro local to the applications
directory (lots of legwork for you, but maybe worth it)
C) Compile the application with JRuby, install the requisite JRuby
jars (there's only one or two, right?), and have the installer install
Java if necessary (relatively easy, since there are lots of templates
and installers that already support installing Java, if necessary)
D) Compile the application using ruby2c or ruby2cext or something
similar, and distribute the program with a static ruby.exe + one huge
honkin .so that it loads.
E) Magically compile the application to a native windows binary.....


I'd say A is in many ways best, since the user then has a full ruby
stack ever-after, but C looks really _really_ inviting too.

--Kyle
Kyle S. (Guest)
on 2009-03-03 18:06
(Received via mailing list)
Note on option B, "Shoes" by why the lucky stiff works this way.
There may be notes on the shoes website about how the installer was
made.  Or he may just share the files for making the installer if you
ask.
Florian G. (Guest)
on 2009-03-03 20:08
(Received via mailing list)
On Mar 3, 2009, at 5:02 PM, Kyle S. wrote:
>
> "Im not concerned about reverse engineering or cracks being made for
> my
> software. All I want is to be able to distribute it the traditional
> way
> like most commercial software is"

In the first post, he also said that he wanted to protect his source
code.

But, i forgot:

http://rawr.rubyforge.org/

is a good option to do that.

Regards,
Florian

--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
Sharagoz -. (Guest)
on 2009-03-03 21:25
Thanks Kyle and Florian, very usefull information
unknown (Guest)
on 2009-03-04 13:01
(Received via mailing list)
> There may be notes on the shoes website about how the installer was
> made.  

Here is a short description on how it works:
http://hackety.org/2008/06/19/stampingExesAndDmgs.html

Mailinglist:
http://news.gmane.org/gmane.comp.lib.shoes

- Axel
David M. (Guest)
on 2009-03-04 13:49
(Received via mailing list)
Rick DeNatale wrote:
>>>
>> That is not entirely true. Or rather, it can be "decompiled", all right,
>> but not into anything resembling the original source code.
>>
>
>
> Actually closer than you might think:
>
> require 'rubygems'
> require 'ruby2ruby'
>

I was speaking of compiled languages in general. As a trivial example, a
common C optimization is to inline functions which are below a certain
size. Now, when decompiling, how do I know what was inlined, and what
really should be duplicate code?

Oh, and not all compiled versions preserve debugging symbols, meaning
any code that isn't actually part of an external API is likely
completely without comments, variable names, method names, etc...

Now, Ruby tends to be much more dynamic, meaning less of the code can be
discarded by the compiler. But that doesn't mean it will look like you
expect. For example:

class Foo
  %w(one two three four five).each_with_index do |name, index|
    define_method(name) { index + 1 }
  end
end

puts Ruby2Ruby.translate Foo

produces:

class Foo <
Object
  def
five
    (index +
1)

end


  def four
    (index + 1)
  end

  def one
    (index + 1)
  end

  def three
    (index + 1)
  end

  def two
    (index + 1)
  end
end

Completely out of order, I have no idea what "index" means in that
context, and it only bears a vague resemblance to the source code used.
David M. (Guest)
on 2009-03-04 14:23
(Received via mailing list)
Sharagoz -- wrote:
> Im not concerned about reverse engineering or cracks being made for my
> software. All I want is to be able to distribute it the traditional way
> like most commercial software is (at least on the windows platform).
>

Great -- glad to hear it. Until you derail the whole thing with:

> Open source makes code stealing too easy.
>

So does distributing software. Again, this will fail. be prepared for
it.

That aside...

> I find it strange that there isnt a compiler readily available for Ruby.
> Is there a technical reason why there shouldnt be one?
>

No. But there are technical reasons it's hard to create one.

The biggest one is reflection:

eval 'class Fixnum; def +(other); 42; end; end'

Imagine the backflips a compiler would have to do in order to allow the
above to work. You'd have no choice but to include the entire compiler
with your program.

If you then start hacking off every piece of metaprogramming and wizardy
that makes Ruby hard to compile, you're killing a lot of what makes Ruby
so great.

> Is it because Ruby is ment to be pure open source and never used in the
> commercial sector?
>

I think the Rails crowd might have something to say about that.

It's not that anyone disapproves of you distributing a proprietary app.
It's just a hard problem that open source people aren't likely to want
to put much time into. After all, open source projects have no problem
distributing as source code.

That said, one of the side effects of JRuby and IronRuby is that you can
probably find a way to compile to Java or .NET bytecode, and I'm sure
there are reasonable ways to either compile these, or distribute them
with something that makes it easy to install the runtime.
Kyle S. (Guest)
on 2009-03-04 18:38
(Received via mailing list)
On Wed, Mar 4, 2009 at 6:21 AM, David M. <removed_email_address@domain.invalid>
wrote:
> No. But there are technical reasons it's hard to create one.
>
> The biggest one is reflection:
>
> eval 'class Fixnum; def +(other); 42; end; end'
>
> Imagine the backflips a compiler would have to do in order to allow the
> above to work. You'd have no choice but to include the entire compiler with
> your program.


Heh.  Just try and use software that relies heavily on reflection in a
compiled language.  Supposedly .Net has reflection nativeley, but the
applications I've used that take advantage of it were horribly slow
and or unreliable.  From what I've seen the compiled applications out
there that use reflection are either trivial, or slow.

--Kyle
Florian G. (Guest)
on 2009-03-04 18:54
(Received via mailing list)
On Mar 4, 2009, at 12:47 PM, David M. wrote:

>>>> decompiled,
>>
>> require 'rubygems'
>> require 'ruby2ruby'
>>
>
> I was speaking of compiled languages in general. As a trivial
> example, a common C optimization is to inline functions which are
> below a certain size. Now, when decompiling, how do I know what was
> inlined, and what really should be duplicate code?


Thats the problem of decompiling native code to a language. Usually,
Bytecodes like Java and .NET are very well decompilable, because they
retain a lot of the language instructions within the code. I suspect
the same to be true for YARV code. For example, inlined Code is
possible in Java, but there are still symbols for determining where it
originates from (for the sake of Backtraces for example).
In the case of Ruby, this also allows you to read stuff like your
dynamic method example.

Regards,
Florian

--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
Randall Alexander (Guest)
on 2009-03-04 21:01
(Received via mailing list)
The Spring Framework uses a lot of reflection yet many would not call it
trivial.  We use reflection in our enterprise because it is the best way
to
solve a problem.



As far as it being slow there are a lot of cavities to that.  It being
slow
used to be the case but the blanket statement of all is not true.  The
reason why it was always slow is because instead of the compiler do a
lot of
the work the interpreter has to do the compilers work now in addition to
what it already had to do with a precompiled class.



If your runtime engine does look aheads (which many modern ones do) then
the
interpreter can have the class evaluated and loaded before it is ever
used.
One of the factors of that working is the size of the class and
everything
the class needs.  We ran a few tests for our enterprise and determined
that
if the class was not a heavy weight class then there was no real
performance
penalty (i.e. response time).  Ironically it actually speed things up
over
the code that needed to do the same thing, in a non "reflection" based
algorithm.



There are a number of other reasons why an application can be trivial or
slow, but it does not necessarily mean it is because of reflection.
Kyle S. (Guest)
on 2009-03-04 21:46
(Received via mailing list)
On Wed, Mar 4, 2009 at 12:58 PM, Randall Alexander
<removed_email_address@domain.invalid> wrote:
> The Spring Framework uses a lot of reflection yet many would not call it
> trivial.  We use reflection in our enterprise because it is the best way to
> solve a problem.
Fair enough.  I never argued that it wasn't the best way to solve some
problems, just that the last time I used a heavily reflected compiled
app (2007?) it was a dog.  I should have made it more clear that in my
experiences were with .Net applications.

> If your runtime engine does look aheads (which many modern ones do) then the
> interpreter can have the class evaluated and loaded before it is ever used.
> One of the factors of that working is the size of the class and everything
> the class needs.  We ran a few tests for our enterprise and determined that
> if the class was not a heavy weight class then there was no real performance
> penalty (i.e. response time).  Ironically it actually speed things up over
Ahh.  The ones I was working in had some pretty heavy classes.  Maybe
reflection wasn't the best way then.  I dunno.  Would you say that a
caveat for efficient reflection is fairly light-weight classes?

--Kyle
Ken B. (Guest)
on 2009-03-05 21:40
(Received via mailing list)
On Wed, 04 Mar 2009 11:52:29 -0500, Florian G. wrote:

>>>>> My second concern is protecting source code. I realize that
>>> Actually closer than you might think:
>
> Thats the problem of decompiling native code to a language. Usually,
> Bytecodes like Java and .NET are very well decompilable, because they
> retain a lot of the language instructions within the code. I suspect the
> same to be true for YARV code. For example, inlined Code is possible in
> Java, but there are still symbols for determining where it originates
> from (for the sake of Backtraces for example). In the case of Ruby, this
> also allows you to read stuff like your dynamic method example.

But decompiling the Java bytecode generated by JRuby would be pretty
much
impossible because it has crazy things in it like call-site caches. The
reason why the Java bytecode can be decompiled into the equivalent Java
source code is because (a) the Java bytecode keeps a lot more
information
around, (b) because Java is the C of the JVM, and (c) because in Java,
the JVM does the optimization, not the compiler.

--Ken
David M. (Guest)
on 2009-03-06 00:37
(Received via mailing list)
Ken B. wrote:
>>>
>> Thats the problem of decompiling native code to a language. Usually,
>> Bytecodes like Java and .NET are very well decompilable, because they
>> retain a lot of the language instructions within the code.
>>
> [snip]
> because in Java,
> the JVM does the optimization, not the compiler.

It's worth mentioning that these are not mutually exclusive.

For example, the LLVM seems to be capable of doing all of the above, to
some extent. They describe it as compile-time, link-time, run-time, and
idle-time optimizations.

I really see no reason you couldn't have a language like Ruby in which
the obvious stuff is pre-optimized beyond recognition, and the more
dynamic stuff is optimized at runtime. In fact, I suspect we'd get most
of this for free, if Rubinius ever finishes that LLVM port I keep
hearing about.

I think my old example still holds:

class Foo
  %w(one two three four five).each_with_index do |name, index|
    define_method(name) { index }
  end
end

A particularly aggressive/intelligent compiler might be able to even
inline that into:

class Foo
  def one
    1
  end
  def two
  ...
end

Each additional compile-time optimization gets harder (both conceptually
and in computation time), because of the nature of Ruby, but also
obfuscates the result that much more.
Charles Oliver N. (Guest)
on 2009-03-06 02:20
(Received via mailing list)
David M. wrote:
> hearing about.
LLVM does no dynamic optimization at runtime; it only does static
optimizations.

The most interesting LLVM project to me is one that uses LLVM as a
backend for the Hotspot JVM (OpenJDK), allowing Hotspot's dynamic
optimizations to couple with LLVM's static ones.

http://icedtea.classpath.org/wiki/ZeroSharkFaq

- Charlie
This topic is locked and can not be replied to.