Stand-alone Neko

Did you know you can bind a neko “.n” file to the neko exe to create a stand-along exe? Well you can, with the “nekotools.exe boot” command. This simply appends the “.n” file to the standard neko.exe, and adds a small footer, giving you an executable that you can run. This is all well and good, except that you will also need to distribute the “.ndll” files, and place them correctly (usually, next to your exe) so that the dynamic loader can find them. This is also not that hard, but is there is an even simpler, single file solution, with no chance of picking up a wrong or development version. The trick is to build a statically linked version of neko.

To do this, you are going to need to compile the source code yourself. I will be using here Visual Studio 2005, express edition because I am tight and it is free. Start by downloading the source from [nekovm.org](http://nekovm.org/download). Currently, neko is at version 1.6.0.
Unpack it and your will get a directory like “neko-1.6.0”, which has sub-directories like “libs” and “vm” in it. I will call this directory “the neko directory”, NEKO. You will also need the garbage collector, “gc”. You can download it from [hp.com](http://www.hpl.hp.com/personal/Hans_Boehm/gc/). Unpack it, and you will get a directory called something like “gc6.7”. Now this is something I’ll be doing with all the extra packages we will be downloading: rename the directory to have no version number, and move it to somewhere in the NEKO/libs directory. ie “NEKO/libs/gc”.

Now start a new empty visual studio project. Set the location to NEKO, so the path names can be relative. I’ve called mine “neko-static”. Untick the “Create directory for solution” (because I hate this option). Exit visual studio and move the “.sln” and “.vc_proj” files out of the “neko-static” directory that VC created against your will into the NEKO directory. (my second most hated feature of VC). Now remove the neko-static directory, and launch the neko-static.sln file. You can leave it in the default location if you wish – I’m just old and stuck in my ways.

Expand out the neko-static folder and add existing items to the Source Files : all the “.c” files from the vm directory, except “gc.c”. (gc.c is not needed since we are using the gc lib).

At this stage if you try to compile you get a bunch dll linkage errors. To get around this, you need to add the -DNEKO\_SOURCES deines, so right-click the project, set the configuration to “All configs” instead of “Active” (THE FEATURE I HATE THE MOST – one of the reasons I prefer makefiles) and in the c++/Preprocessor/Proprocessor Definitions add “NEKO\_SOURCES”. This says we are building and exporting neko, not importing a dll.

If you compile now, you will get an error in alloc.c finding gc/gc.h, because it is in the “include” directory, not the base. I think the easiest way to fix this is to edit alloc.c to #include “libs/gc/include/gc.h”.

Now you get a bunch of “\_\_imp\_\_GC\_ …” undefines. This tells me that we are using the dynamic import version for gc, so also change the #define of “GC\_DLL” to “GC\_NOT\_DLL” in vm/alloc.c. Now we get the static versions undefined, which is what we want – fix this by creating a sub-folder in the project “Source Files” called “gc” and add the files:
allchblk.c alloc.c blacklst.c checksums.c dbg\_mlc.c dyn\_load.c finalize.c headers.c mach\_dep.c malloc.c mallocx.c mark.c mark\_rts.c misc.c new\_hblk.c obj\_map.c os\_dep.c ptr\_chck.c reclaim.c stubborn.c typd\_mlc.c win32\_threads.c.
*Hint: instead of using the “Existing item” dialog from the project, you can keep an explorer window open and drag in the files you want*.

I initally made the mistake of putting “gc\_cpp.cpp” in the project. This overrode the “new” operator and sent eveything through gc. It worked,
but was much slower (you could hear the hard drive grinding) (Edit:maybe it was the log file ?).

And add to the project the include directory “../libs/gc/include/” from the project properties (don’t forget my most hated feature) in c++/General/Additional Include Directory.

Now there are only a couple of errors. In builtin.c, comment out the “\_ftol2” function. Add the defines :GC\_NOT\_DLL;GC\_WIN32\_THREADS,
and add the “Linker/Input/Additional Dependencies” user32.lib. While you are there, add \_CRT\_SECURE\_NO\_DEPRECATE to the defines, and
4996 to the Advanced/”Disable Specific Warnings” for more reasonable output.

I now have a “Debug/neko-static.exe” that can be run. Not that it will do us much good, because it has no libraries, and crashes on:

class Test
   { public static function main() { neko.Lib.print("Hello static world.\n"); } }

because it finds the “std.ndll” from NEKOPATH. Because it is statically linked, it will not work properly with any extenal ndll files.
We can get around this with a simple trick. In “load.c”, instead of using

h = dlopen(val_string(pname),RTLD\_LAZY);

Use:

h = GetModuleHandle(0);

This is quite neat, because any “\_\_dllexport” functions will be accessable will be visible from the exe module.

Now the program just fails because there is no std library. Fair enough – just add one: Create in “Source Files” filters “libs” and “libs/std”, and
add all the .c files from libs/std. “neko.h” is not found, so add “vm” to the include path (DFMHF), and add “wsock32.lib” to dependencies. Also, comment out “_ftol2” from math.c.

Now build – hey presto a stand-alone neko exe!

One more trick – before adding the “.n” bootstrap onto the end, compress the exe using the rather satifying exe-packing program, [upx](http://upx.sourceforge.net/). You need to do this first, because the script will be read from the original file on disk, not the decompressed image in memory.

So you get:neko-static-upx.exe that you can use as a base. To build an exe, you can use the “nekotools.exe boot -b neko-static-upx.exe Test.n”. If neko has trouble finding the exe, place it in the $NEKO\_INSTALLPATH directory. This exe should run anything that uses only the “std” library (sadly not “regexp”).
There is one bug with this build, it generates “gc.log” files. I will have to track down the flag to disable this.
So witness my opus:

test.exe

*Note: Now, I’m no lawyer (as all good legal opinions start), but all the code here will be using the LGPL license (or more liberal). My understanding is that the spirit and letter of the law means that if you compile with LGPL code, you should give everyone the right to __RELINK__ your code with a different version of the LGPL code. Normally this is done with DLLs, since this is simple. In this case, it is being done with the “.n” file you are embedding. ie, there is no reason why someone could not relink your exe using the excact same procedure above. You do not need to give them your haxe source code, only your “.n”. However, it does mean you can’t do any tricky hidden DRM stuff in the exe, without surrendering the appropriate “.obj” file.*

“Harr”, I hear you say, “that is satisfying”. But wait, there’s more.

nekodirectories.png

Wouldn’t it be cool if you had a simple base you could use for all your gaming? Well, it can be done. To statically link against NME, you need to gird your loins and download the following packages:

– SDL-1.2.12.tar.gz
– SDL_mixer-1.2.8.tar.gz
– SDL_image-1.2.5.tar.gz
– SDL_ttf-2.0.9.tar.gz
– libogg-1.1.3.tar.gz
– libvorbis-1.0.0.tar.gz
– freetype-2.3.5.tar.gz
– pcre-7.4.tar.gz

I ran out of steam and just commented out the “sge” library bits, and stopped at ogg audio (untested) (sorry Lee).

If you are not interested in gaming , the regexp bit may still be appropriate.
I extracted the pcre library to libs/regexp and renamed it “pcre”, and the “hand configured” by

cp  pcre.h.generic  pcre.h
cp  config.h.generic  config.h
cp pcre_chartables.c.dist pcre_chartables.c

Added ‘#include “config.h’ to top of pcre.h and removed “HAVE\_DIRENT\_H” define. I then added the c files (skipping the example files that define a “main” function) as well as “libs/regexp/regexp.c” to the project in a sub-folder.

I copied the NME source files from the “project” folder of the “haxelib” version of NME. I then added some extensions for blink, and commented out the sge stuff because there are only so many libraries you can add in an evening.

I created an “sdl” directory in the NME directory (should have probably stuck it next to it) and extracted all the above libraries and renamed them without their version numbers. I then painfully selected source files from these libraries for the project. Some things to note:

– #define OGG\_MUSIC from the project properties.
– #define \_WIN32\_WINNT=0x400 to get TRACKMOUSEEVENT
– Added each of the packages somewhere in the include path, eg: libs/nme/sdl/SDL/include libs/nme/sdl/SDL\_image libs/nme/sdl/SDL\_mixer etc.
– Added SDK path the get ddraw.h (additional download required for VS express edition)
– #define FT2\_BUILD\_LIBRARY to say we are building it, not using it.
– When adding files from freefont, you only need to add one from each “driver”.
– I commented out the “GC_write” function to try to stop the log.

When compiling modules with “DEFINE\_ENTRY\_POINT”, you get a multiply defined symbols. So I commented these out (could probably have done something in the header), and added specific calls to these boot routines in vm/main.c.

There, if you are still awake, you have it. The final output is the base: neko-nme-upx.exe(615k) which will run the BlinkDemo “.n” files (and any standard program that uses “std” and “regexp”) without and additional help. And see the stand-alone programs:

robotdemo.exe (765k)

cardemo.exe (760k)

Plenty of stuff still to be done, such as “subsystem:windows”, more audio, sge etc, but
I think this is an excellent way to deliver games (or utilities for that matter), without fear of DLL hell. It also sidesteps “manifest hell” that microsoft seems keen on inflicting on us by insisting that the vc8 dynamic runtime is installed in a central location. I think the logic goes “if .net apps have to have a separate runtime installer, every one has to too”. What a stupid solution to force when the simple “just put the dll in the application directory” has worked for decades. (sorry about the rant).

It runs faster, too!

6 Replies to “Stand-alone Neko”

  1. I don’t know if you’re still working with this (although I’m picking up a lot going tohrough it), but the current (3/2009) version (1.8) has most of this built-in. I did have to comment out some externs to get it to compile, though (at least, in VC2005).

    But the reason for the comment: adding SILENT to the preprocessor definitions turns off the logging in the garbage collector.

  2. Asking because I was trying to use a small program that checks if servers are up and emails someone if they aren’t, at work. It uses mtwin. It simple locks the server everytime I try it, even with the libs by its side in the same directory.

Leave a Reply

Your email address will not be published. Required fields are marked *