Thursday, April 3, 2014

Compiling pharo-vm on SnowLeopard (OSX 10.6)

As indicated on the pharo-vm page, apart Xcode, you also need git, wget, cmake, gnu tar with xz (for uncompressing cairo librairy). There are simple instructions to install these. If you're not too special, follow them. If you like sport, read this.

My OS/hardware is behind, my disks are all crowded, I want to control what is installed. I decided to keep my ancient Xcode version (3.2.6), install from dmg packages what could be (cmake, git - BEWARE, not a recent git, 1.7.12 will do see previous post) and the remainder via source code (wget, tar, xz).

There is no special difficulty, except that wget must be configured with
$ ./configure --with-ssl=openssl
$ make
$ sudo make install

If some documentation fails to generate (gettext?), never mind, proceed.
One must also arrange to have gnu tar taking precedence over, or replacing default tar, I omit the details here, I'll come back to it.

After cloning the pharo-vm repository (see previous post), let's produce a VM.
$ cd image && ./newImage.sh
$ ./pharo generator.image eval 'PharoVMBuilder buildMacOSX32'

Bad news, with such configuration, the automated procedure does not work for me.

0. Starting the image interactively

This is required for debugging, but provided ./pharo command seems to allways start headless.
I have too many different VM around for the normal Mac GUI to be efficient. Since I may restart many times, and since git will force me to use a shell anyway, a command line is perfect, let's pick some 2.0 VM installed somewhere else:
$ ~/Smalltalk/Squeak/pharo/Pharo.app/Contents/MacOS/Pharo generator.image

Now let's jump the hurdles...

1. Generated source does not compile

Many compilation errors... the include files are not found!
Haha, the path to SDK provided thru -isysroot option is not that of my machine...
My fault, I did not want the latest Xcode, but why should I?

Good Point: this is not in an obscure configuration file hidden somewhere on the disk, but a method directly accessible from the generator.image. It can be discovered by extended search / literal string with it: 'Xcode' or 'sysroot' lead to it.

Solution: I had to change 
CogFamilyCocoaIOSConfig>>setGlobalOptionsAfterDetermineSystem:  maker
    maker set: 'CMAKE_OSX_DEPLOYMENT_TARGET' to: '10.5'.
    maker
        set: 'CMAKE_OSX_SYSROOT'
        to: '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX', self sdkVersion, '.sdk'

to
        to: '/Developer/SDKs/MacOSX', self sdkVersion, '.sdk'


Bad point, I'm not on the automated route anymore, before going back to automation, I must patch one of the MC packages with something that appear as very platform/installation specific... Then I'll have to constantly care about what i stage, commit and push back on github.
The right solution could be to automatically discover the path, maybe with some heuristics. Isn't it some sort of cmake base service?

While at it, I also changed cairo rules to use /usr/local/bin/tar for my specific installation:
CMCairo>> unpack
    gen set: #unpackTarget toString: '${libSourcesDir}/touch.cmake'.
    gen puts:
'add_custom_command(OUTPUT "${unpackTarget}"
        COMMAND /usr/local/bin/tar -Jxf "${archiveFileName}"
        COMMAND touch "${unpackTarget}"
        COMMENT "Unpacking ${libName} ... "
    )

'.

2. Generated CMakeLists.txt has syntax error

Huh??? This did not occur at first attempt...
Haha, the syntax errors are near the end of file...
It reminds me something... Ah yes, read the comment of StandardFileStream>>padToEndWith:
The files have been overwritten but not truncated!
Bad luck, the path to my SDK was shorter than original...

Solution: remove the build dir content and restart build.
$ rm -rf build/*
$ ./pharo generator.image eval 'PharoVMBuilder buildMacOSX32'

Quite large a hammer, this could certainly be more selective.
Anyway, this is an error prone manual operation, and should be in the automated procedure. Or the truncation story should better be fixed either in image or in VM.

3. libgit2 thirdparty library is not compatible

There is an error at link this time: no such thing as strnlen in my standard libraries.
Fortunately, this is a known problem, already solved for mingw case by defining a p_strnlen.

Solution: I directly patched an include file to apply the known cure:
$ vim build/thirdParty/libgit2/libgit2-0.20.0/src/posix.h

where I replaced:
# define p_strnlen strnlen
with:
GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
        const char *end = memchr(s, 0, maxlen);
        return end ? (size_t)(end - s) : maxlen;
}

 

A Future version of libgit2 should fix it I hope, and the installation script should be changed to point to that version. Right now, I am again getting further away from automated route... Specially if build directory has to be erased at each code generation!

4. VM compiled by cmake fails to run a Pharo image

At least, it fails frankly, here is how:
$ ../results/Pharo.app/Contents/MacOS/Pharo generator.image
Bus error.

Err, so many hours going up in smoke, that can't be...

Solution: let's debug by generating a Xcode project from cmake and generating a VM from Xcode:
$ cd build
$ rm CMakeCache.txt 
$ cmake -G Xcode

Good news, that worked without error.


Hooray! But what's the difference ??? I can't tell, but at this stage, I don't care, I can test my changes with the right invocation:
$ ../results/Release/Pharo.app/Contents/MacOS/Pharo generator.image

5. Conclusion, it worked finally!

The object of this post is not to rant against Pharo team. On the contrary, hat down to Igor, Esteban, Camillo, and whoever participated, a huge work has been accomplished in the right direction, and it's me who departed a bit away from the official procedure.

But see how switching tools costs. Four evenings in my case including git, not accounting the time to blog it, let's hope that the investments will pay. This deserves some feedback. It's not that configure is better than cmake, nor svn than git, I think quite the contrary. I would expect more resilience though. The process is not polished enough.

I perfectly understand Pharo's choice. Squeak procedure was easier when not innovating too much, but adding cairo support is a sufficient reason for reconsidering what easy means!

It should be possible to automate all my actions. Once those low branded workarounds polished, they might be aggregated. Of course, this would be at the cost of maintaining a more and more complex CMakeVMMaker...

The opposite solution is to support only a restricted set of hard/soft platforms, and let every other one deal with its own problems, but how good is it in the long term? Everything rots, it's a source of future frustrations, and might restrain good wills.

For my tiny experimentations, I'm back to a an old school image based and hand crafted procedure. That's all right. But I must quickly write this post, at least it will help myself.

I'll retain the two very good points:
  • the compilation details are configured from within the image with CMakeVMMaker (at least, dirty hacks are easy)
  • a single repository with consistent platform specific C code and Smalltalk VMMaker code
 Now, let's concentrate on the vm content. We'll see later about the harder parts
  • how to manage the workflow with MC, filetree, github and my special brand
  • how to reconcile Eliot's work.

No comments:

Post a Comment