Coding and more – Concrete5, Flex, JavaScript

Statically linked Linux executables with GCJ, Seed7 and haXe

While some of you might try to avoid statically linked executables, they can be quite handy. In my case there are situations where I quickly have to run some code on a shared hosting with limited access. Installing libraries isn’t possible but running binaries is – at least if you have something like SSH access like I mostly do.

The exact reasons why I don’t run a PHP, Ruby or Python script are a bit more difficult. Just believe me that I needed a binary file without the ability to install any additional libraries ;-)

To do this, I toyed around with a bunch of different languages. This list is certainly not complete but I’m happy to extend it if you have any suggestions. Please note, I didn’t include languages like C intentionally because I also didn’t want to see things like malloc in my code. At this point you probably think that I’m a rather complicated person and yes, you’re probably quite right about that.

Enough about that, the first languages/compilers I’ve had a look at on my Debian box if you following the link..

GCJ

Java is a mature language with great documentation, tuns of tutorials and examples – certainly good enough to do almost anything one could imagine. The common JRE won’t work in my case since I’ve intended to build a static executable.

This is why I’ve installed GCJ – the GNU Compiler for Java. This can be done quite easily on Debian with the following command

1
apt-get install gcj

A little bit later, everything was installed, ready to create the well known and complicated hello world file hello.java with the following content:

1
2
3
4
5
public class hello {
  public static void main(String argv[]) {
    System.out.println("Hello from static executable");
  }
}

A quick look in the documentation shows that as of GCJ version 4.2 there’s a simplified parameter -static-libgcj which we can use instead of calling gcc with a bunch of different parameters as shown below too. So far everything looked easy.

1
gcj hello.java -o hello --main=hello -static-libgcj

The more complicated way before GCJ 4.2:

1
2
3
gcj -c hello.java
gcj --main=hello -save-temps hello.java
gcc -o hello hello.o hellomain.i -shared-libgcc -Wl,-non_shared -lgcj -Wl,-call_shared -lsupc++ -Wl,--as-needed -lz -lgcc_s -lpthread -lc -lm -ldl -Wl,--no-as-needed

However, when I executed the first command on my Debian I’ve got an error because libgcj isn’t available on Debian. I found a few topics about that and didn’t bother to delve a lot deeper into this when I found a pre compiled version on http://download.berlin.freifunk.net/sven-ola/freenet/.
I quickly downloaded the missing libgcj.a and run the command again.

VoilĂ , there was an executable without any dependencies. This can be checked with a command like this by the way:

1
2
3
4
5
6
7
8
9
10
11
12
13
linuxbox:~/gcj# readelf -d hello
 
Dynamic section at offset 0xb3c848 contains 28 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [librt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libz.so.1]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld-linux.so.2]
...

However, I was a bit surprise to see that the file was more than 40MB. This makes sense if you consider that all these Java functionality has been linked into that file, but I don’t really care, it’s just a simple hello world and having such big executables on my shared web hosting is a bit too much. There might have been a way to compress that file or remove some unused calls but I wasn’t in the mood to do that so I moved on to the next language.

UPDATE 08.08.2011: As mentioned by Scott, strip removes quite a lot of stuff from the executable. After running strip, I was able to shrink the file to 34% of its original size:

1
linuxbox:~/gcj# strip hello

Seed7

Seed7 is not very well known language but if you have a little Pascal, Oberon, PL/SQL background like I do, it will look a bit familiar. The language itself isn’t difficult to learn, there are now fancy language features, it’s a nice and simple language. But please note, I’m not very familiar with Seed7, these are just my first impressions. Happy to take feedback about that!

There wasn’t a Seed7 Debian package available. I therefore downloaded and compiled everything on my own which is rather easy. There are a lot of releases, you might want to check this page for new versions http://sourceforge.net/projects/seed7/files/seed7/ and replace the link below.

1
2
3
4
5
wget http://downloads.sourceforge.net/project/seed7/seed7/seed7_05_20110522/seed7_05_20110522.tgz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fseed7%2Ffiles%2Fseed7%2Fseed7_05_20110522%2F&ts=1307042936&use_mirror=netcologne
tar xf seed7_05_20110522.tgz
cd seed7/src
make depends
make

Done! There are several examples shipped with the file we’ve downloaded, let’s have a look at the first one.

1
2
cd prg
./hi hello.sd7

This prints “hello world” along with some other stuff we don’t really care about right now. This looks a lot like an interpreter, doesn’t it? Yes, but there’s a Seed7 interpreted file which produces C code and automatically calls GCC. Let’s try this as well:

1
2
./hi comp.sd7 hello.sd7 -O2
./hello

As Sven pointed out, if you add -O2 the resulting exe will be a bit smaller. In my case the file was 365KB, compared to 461kb without -O2 in size and has a dependency on X11 and ncurses which we can see if we run “readelf” again:

1
2
3
4
5
6
7
8
9
linuxbox:~/seed7/seed7/prg# readelf -d hello
 
Dynamic section at offset 0x28014 contains 24 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libX11.so.6]
 0x00000001 (NEEDED)                     Shared library: [libncurses.so.5]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 ...

This looks quite good so far but since Seed7 isn’t very popular, you might have some difficulties finding tutorials, examples, libraries etc. As Sven mentioned too, there are several libraries Seed7 available on this page http://seed7.sourceforge.net/libraries/. I couldn’t find a lot of examples at first and I still get the impression that most of these libraries haven’t been widely used yet. I quickly tried to implement a small socket server but stopped when I couldn’t find any kind of “select” method to handle multiple clients the way I want. However, I got a message to Thomas Mertens, the author of Seed7, which caused me to have a third look at Seed7. It’s important to know that you get several examples when you download Seed7. Among others, there’s a small webserver as well a basic interpreter which impressed me quite a bit.

Seed7 might still need some popularity but it seems to be quite solid and well thoughout. I also found this page http://rosettacode.org/wiki/Seed7 which helped me a lot since I was able to compare different languages to Seed7 and get a first impression on how I can implement a few basic things in Seed7.

In my case Seed7 would actually have worked, but just for the fun of it I wanted to try something else, next language!

haXe

haXe is also a relatively new language. haXe is a so called multiplatform language which targets different platforms like JavaScript, Flash, NekoVM, PHP, C++, C# and Java. Quite an impressive list I’d say but unfortunately most of them are still in work which is why you might run into some issues.

The syntax looks a lot like Java, C# and easy to learn for people who have some experience with such languages. Since I’m trying to build a statically linked executable I went for the C++ target. I’ll save you the time, there’s a pre built package available for Debian but hxcpp doesn’t seem to work with it right now. But don’t worry, building from source is very easy:

1
2
3
4
5
6
7
wget http://haxe.org/file/hxinst-linux.tgz
tar cf hxinst-linux.tgz
chmod +x hxinst-linux
./hxinst-linux
mkdir -p /usr/lib/haxe/lib/
haxelib setup
haxelib install hxcpp

This downloaded and installed haXe, installed the libraries and also installed the hxcpp target by using haxelib. haxelib seems to be the tool which you can use to install, upgrade your haXe tools and a few more things. It’s very intuitive to use, a bit like RubyGems or PECL for PHP.

Let’s create our first haXe hello world file “Test.hx”

1
2
3
4
5
class Test {
    static function main() {
        trace("Hello World !");
    }
}

When then create a file called compile.hxml which we’re going to use to build the executable:

1
2
3
-cpp cpp
-debug
-main Test

Last but not least, we’re going to build our executable by running:

1
haxe compile.hxml

A bit later we’ll find an executable called “Test” in the subdirectory “cpp”. It’s only about 200KB and doesn’t have any fancy libraries included:

1
2
3
4
5
6
7
8
9
10
11
linuxbox:~/haxe/cpp# readelf -d Test
 
Dynamic section at offset 0x358a0 contains 26 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
...

haXe seems like a very interesting concept, as with all new things, there aren’t too many tutorials or examples around. The forum is also not very active, most of the discussion seems to be in the mailing list. haXe also seems to be a possible choice, I’m just a bit worried that I might run into some issues which haven’t been solved yet. Supporting a language with so many different targets isn’t easy and attracts all kinds of needs.

I’ll probably try to build a few things with haXe and see where it goes.

12 Responses to “Statically linked Linux executables with GCJ, Seed7 and haXe”

  • Sven Torgensen

    Thank you for the nice article. I have comments regarding Seed7:
    1. Seed7 goes byond Pascal. It is extensible and has many advanced features, like user defined statements (see Seed7 FAQ).
    2. The Seed7 compiler accepts the option -O2, which reduces the size of the executable.
    3. There are several libraries (approx. 50 of them) shipped with Seed7 and this libraries are discribed at:
    http://seed7.sourceforge.net/libraries

    Have a nice day
    Sven

  • Remo Laubacher

    Hi Sven, thanks a lot for your answer! I’ll try to update my article as soon as possible! When I mentioned Pascal I was basically thinking about the syntax, not so much about the features itself. The code looks a bit like Pascal, I’m sure Seed7 has more/new features when compared to Pascal.
    Remo

  • Scott Gilbertson

    > [GCJ] There might have been a way to compress that file or remove some unused calls

    The output of GCJ contains a lot of symbol information, which is only really useful if you want verbose stack traces. Those symbols can be removed like so: strip hello

  • Remo Laubacher

    Scott, you’re right, I was able to remove almost 28MB, making a total of 14MB. Still big for a hello world but a lot better! Thanks!

  • Sven Torgensen

    Debugging information can be removed from every executable. E.g.: Applying strip to the compiled hello world example of Seed7 reduces it to 130408 bytes.
    BTW: I don’t see that it has a dependency on X11 and ncurses. Maybe this is because I use the latest release ((2011-10-03).
    BTW2: The option to optimize is -O2 (without space).
    Thank you for the link to Rosetta Code
    ( http://rosettacode.org/wiki/Seed7 ), I was not aware of it.

    Have a nice day
    Sven

  • Remo Laubacher

    Sven, thanks for you comment! As a matter of fact the dependencies have been removed in a recent version!

  • Ferhat Dogru

    Hi Remo,

    I heartily enjoy articles of this kind and really love to see that you simply used some “lesser-known” languages to see if they do the job better without prejudices or unnecessary caution regarding feature completeness.

    Thanks for that Remo!

    Languages useful for mathematical solutions that come into my mind are J(-Programming Language) and Julia. http://www.jsoftware.com/ and http://julialang.org/ I’ve experimented a little with APL, but J is free, where APL is not.

    I’m going to look into http://www.zimbu.org/ and http://chapel.cray.com/ a little more because they look much more promising

    I’ve run some benchmarks with Opa it’s not the fastest out there, but it’s quite secure as far as I’ve tested. http://opalang.org/ I guess it won’t run on most hosts though.

    Best wishes
    Ferhat

  • Remo Laubacher

    Hey Ferhat,

    thanks for those links! I’ve played around with Julia before (the programming language I mean) but didn’t really like the syntax. Never heard of Zimbu or Opa but those looks really nice! Opa might not be the fastest but it’s looks very clean and the documentation also looks rather complete!

    I’ll try to have a look at these languages soon and post another article about it. I didn’t get many visitors on this article but I like that kind of stuff a lot. Glad I’m not the only one ;-)

    Remo

  • Ferhat Dogru

    heheh I know you played with Julia ;)

    It’s a lot better than APL/Matlab/R can’t tell if it’s better than J,
    but the advantage of Julia is that it’s a lot easier to learn than J, which is a greaaat Plus.

    There’s another great thing that I’m playing around with a lot, that is the G-WAN Application Server.
    http://gwan.ch/ I’d visit the Author if I was in wonderful Switzerland :)
    You can use any number of languages within it, that’s why I also played with Julia ;)
    It’s great as Back-End language for Stochastic Operations on Data-Sets that are processed with ANSI C (scripts).

  • Sven Torgensen

    Hi Remo,

    Recently I took a look at Seed7 again. There were some changes.
    Interpreter and compiler have been renamed. The new names are s7 and s7c.
    The compiler now produces smaller executables. On my machine the executable
    of the hello world example has a size of 49063 bytes.

    I found also some progress in the area you mentioned (small socket server).
    There is a type named pollData, which provides an interface to poll() (see
    http://seed7.sourceforge.net/libraries/poll.htm ). A higher level interface
    via the function waitForRequest seems to simplify the task of writing a
    server even more (see http://seed7.sourceforge.net/libraries/listener.htm ).
    This higher level interface is used in a ftp server example.

    For people, who use Windows, there is also a self extracting archive of
    Seed7 (see http://sourceforge.net/projects/seed7/files/bin ).

    There are also other improvements, but I want to save some space here. :-)

    Have a nice day
    Sven

  • Remo Laubacher

    Thanks a lot for the follow-up, much appreciated!
    I’ll try to have another look at seed7 someday but I have to finish a few things first before I can spend time on these fun learning things..

  • Leave a Reply