Ruby on Windows CE & Pocket PC
There is already a version
of Ruby for the Pocket PC and a 'wince' directory in the Ruby source
package, so you can, in theory, build it yourself. However, getting it
working is easier said than done; it relies on Microsoft Embedded
Visual C++ and the Windows Mobile / Pocket PC SDK toolkit.
Even once you've got those installed and working it really doesn't want
to play :-(
Just look at all the newsgroup postings that complain about it:
http://www.ruby-forum.com/topic/31143
http://www.ruby-forum.com/topic/48735
http://www.ruby-forum.com/topic/58497
http://www.ruby-forum.com/topic/57994
Even using the pre-compiled version from the Japanese site, if it runs on your device (I tested three, it worked on one), there are issues with string handling
Efforts Abanded: Jan, 2009
Without any updates for such a long time I felt it time to say that I
have abandoned this project.
My efforts were continually bumping up against the memory limits on
such small devices and the lack of a relative filesystem makes testing
existing code *extremely* annoying and time consuming.
Work pressures have stopped me from working any further on the codebase
and patches and I unfortunately no longer have the desire to persue this
any further in my personal time. I have uploaded the last patch I made
against Ruby 1.8.6-p114. Hopefully someone else will find it useful.
It's in the download section here.
Update: 1st Mar, 2008
Did a little bit more work during the evenings this week. Seems to be
some problems with Gem that I can't work out. Having got very close to
a working install of Rails I'm now spending time porting the regression
tests included in the ruby source code to work on Windows CE (mostly
relative 'require' path problems). See here for more info.
Sockets work in the latest 240208 -O3
build below :-)
Update: 24th Feb, 2008 (fourth time is a charm!)
One last post until I sign off for the weekend.
Sockets work in the latest 240208 -O3
build below :-)
Update: 24th Feb, 2008 (third time today!)
One final build for the weekend (check -O3
optimised, this time which does seem to make it a little quicker.
Try running "ruby /ruby/bench.rb" - this the routine listed here.
Update: 24th Feb, 2008 (second time today!)
Another build (check here for the
files), this time I think I've solved the socket extension problem,
well it loads when you do a 'require' now... as a bonus Gems now
installs and works! Have a look!.
Update: 24th Feb, 2008
I've created a patch against my modified Ruby source code, so it should
be a lot easier to build your own Ruby/WinCE/ARM binaries now. I will
do a bit more testing before releasing it, as it needs an error library
from CEGCC project, but it does look promising.
Let's get started..
The Theory:
The theory behind this is that building Ruby as a native 'Posix'
application we don't need to get into all of the hassle with the
Microsoft tools, and, hopefully, we can solve that horrible
wince::strerror problem that seems to plague the natice Windows CE
build.
Before we start...
This is sounding like Blue Peter! Stay with me though... Anyway, this
guide presumes you are familiar with either Cygwin, the
Unix-like compatability suite of programs for Windows, or an x86
flavour of Linux. The process will work for other Unix
environments, but you will need to build some of the tools used in the
process yourself.
If you have no experience with those environments then this guide is
not for you. However, I do have a pre-built Ruby binaries for you to
test on your Windows Mobile or Pocket PC device. Check them out here.
Required 'Stuff':
- The normal GNU development toolchain (gcc, make, yacc etc..)
- The CEGCC Project
cross-compilation toolchain. Either Cygwin or Linux version, depending
on your operating system. You do not need the mingw32 version as we
will be building for Posix environment, not a Win32 CE environment.
- The Ruby source
code release (this process is written for 1.8.6-p111, but should be
applicable to subsequent releases).
- A working Ruby installation on your own machine. This is needed to
automatically construct some of the makefiles during the build process,
obviously if you're compiling Ruby for a different architecture the
binary you create won't run on your computer!
- Some sort of console program to run on your Pocket PC device.
Microsoft offers the Windows
Mobile Powertoys for Pocket PC 2003, or you could use this version
of PocketConsole which
works on both Pocket PC 2003 and Windows Mobile 5+.
- Presumably, some sort of Pocket PC or Windows Mobile device powered
by an ARM or Xscale processor. Either a physical device, or you can use
the emulator from Microsoft.
Installing the Tools:
On my system I installed the CEGCC toolchain in the following location:
/exportATA/development/wince/cegcc
Ruby source is unpacked into:
/exportATA/development/wince/src/ruby-1.8.6-p111
All the following commands assume those locations, you will need to
alter any paths to suit your environment.
Setting up the dev Environment:
I have a bunch of aliases in a file (crosscompile.config) in case
the configure script doesn't detect everything quite correctly,
download this and put it one level above your Ruby source directory. Do
a source crosscompile.config before
running configure.
You'll have to set a few LDFLAGS and CFLAGS to get Ruby to build
successfully. This is the configure command that I ran:
CC=arm-wince-cegcc-gcc \
CPP=arm-wince-cegcc-cpp \
CPPFLAGS="-D_LINUX_SOURCE_COMPAT" \
LIBS="-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib
-I/exportATA/development/wince/cegcc/arm-wince-cegcc/include" \
LDFLAGS="-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib" \
ac_cv_func_getpgrp_void=yes \
ac_cv_func_setpgrp_void=yes \
ac_cv_sizeof_long_long=8 \
ac_cv_func_memcmp_clean=yes \
ac_cv_func_memcmp_working=yes \
./configure \
--disable-ipv6 \
--target=arm-wince \
--host=arm-wince \
--with-static-linked-ext \
--disable-shared \
--prefix=/ruby \
-C
The ac_cv
lines are required, otherwise the configure script actually tries to
check that the 'setpgrp' function works, which doesn't make much sense
when you're building for a different architecture! The best solution I
suppose, would be for someone to put a check in the configure script so
that those tests are not run if it detects that we are cross compiling.
Assuming that the configure process completes ok, then we now need to
edit the main Ruby makefile to use our own ruby installation - we can't
continue if we don't do this as we will get errors referring to a
missing ruby:
$ make
make: miniruby.exe: Command not found
make: *** [.rbconfig.time] Error 127
Change the Makefile so that MINIRUBY is set to your
actual local Ruby interpreter, e.g. MINIRUBY= /usr/local/bin/ruby
Compiling Ruby - Part 1 - miniruby:
At this point if you try to build the miniruby binary you will get
something like this:
$ make miniruby
rbconfig.rb updated
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -I. -I. -D_LINUX_SOURCE_COMPAT
-c array.c
...
...
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -I. -I. -D_LINUX_SOURCE_COMPAT
-c dmyext.c
arm-wince-ar rcu libruby-static.a array.o bignum.o class.o compar.o
dir.o dln.o enum.o error.o eval.o file.o gc.o hash.o inits.o io.o
marshal.o math.o numeric.o object.o pack.o parse.o process.o prec.o
random.o range.o re.o regex.o ruby.o signal.o sprintf.o st.o string.o
struct.o time.o util.o variable.o version.o crypt.o flock.o dmyext.o
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -I. -I. -D_LINUX_SOURCE_COMPAT
-c main.c
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -L.
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib main.o
libruby-static.a -lm
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib
-I/exportATA/development/wince/cegcc/arm-wince-cegcc/include -o
miniruby.exe
Info: resolving _CRT_MT by linking to __imp__CRT_MT (auto-import)
Info: resolving environ by linking to __imp_environ (auto-import)
Info: resolving __ctype_ptr by linking to __imp___ctype_ptr
(auto-import)
libruby-static.a(io.o): In function `pipe_open':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/io.c:3113:
undefined reference to `fork'
libruby-static.a(process.o): In function `get_ppid':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/process.c:165:
undefined reference to `getppid'
libruby-static.a(process.o): In function `rb_f_fork':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/process.c:1288:
undefined reference to `fork'
libruby-static.a(process.o): In function `rb_proc_exec':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/process.c:1063:
undefined reference to `execl'
libruby-static.a(process.o): In function `rb_f_system':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/process.c:1533:
undefined reference to `fork'
collect2: ld returned 1 exit status
make: *** [miniruby.exe] Error 1
The problem is that CEGCC gives us a 'mostly' Posix compatible
interface, but it is missing some system calls under Windows CE,
notably; 'fork', 'execl' and 'getppid'. But it does
have 'vfork' and 'execv'.
Patching
You will need to patch process.c and io.c as follows:
diff patched_process.c process.c
165c165
< return INT2FIX(0);
---
> return INT2FIX(getppid());
1063c1063
< execv("/bin/sh", str);
---
> execl("/bin/sh", "sh", "-c", str, (char *)NULL);
1288c1288
< switch (pid = vfork()) {
---
> switch (pid = fork()) {
1533c1533
< pid = vfork();
---
> pid = fork();
diff patched_io.c io.c
3113c3113
< switch ((pid = vfork())) {
---
> switch ((pid = fork())) {
That should get you a shiny miniruby binary:
$ make miniruby
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -L.
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib main.o
libruby-static.a -lm
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib
-I/exportATA/development/wince/cegcc/arm-wince-cegcc/include -o
miniruby.exe
Info: resolving _CRT_MT by linking to __imp__CRT_MT (auto-import)
Info: resolving environ by linking to __imp_environ (auto-import)
Info: resolving __ctype_ptr by linking to __imp___ctype_ptr
(auto-import)
$ ls -l miniruby.exe
-rwxr-xr-x 1 megatron users 1903849 2008-02-23 14:12 miniruby.exe
$ file miniruby.exe
miniruby.exe: MS-DOS executable PE for MS Windows 32-bit
Reducing file size
If you're happy with just a miniruby executable, you can strip the file
to reduce the size:
$ arm-wince-cegcc-strip miniruby.exe
$ ls -l miniruby.exe
-rwxr-xr-x 1 megatron users 641536 2008-02-23 14:16 miniruby.exe
Compiling Ruby - Part 2 - ruby and extensions:
If you run make
now, then it should start building any of the extensions you have
chosen I have not investigated all of the extensions, but most appear
to build without issue. However there are several that do not build:
ext/dl
make[1]: Entering directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/dl'
Generating call.func
void
char
short
long
float
double
arm-wince-cegcc-gcc -I. -I../.. -I../../. -I../.././ext/dl
-DHAVE_WINDOWS_H -DHAVE_GETLASTERROR -DHAVE_FREELIBRARY
-D_LINUX_SOURCE_COMPAT -I. -g -O2 -fno-defer-pop
-fno-omit-frame-pointer -c sym.c
arm-wince-cegcc-gcc -I. -I../.. -I../../. -I../.././ext/dl
-DHAVE_WINDOWS_H -DHAVE_GETLASTERROR -DHAVE_FREELIBRARY
-D_LINUX_SOURCE_COMPAT -I. -g -O2 -fno-defer-pop
-fno-omit-frame-pointer -c handle.c
handle.c: In function 'rb_dlhandle_initialize':
handle.c:66: warning: passing argument 1 of 'LoadLibraryW' from
incompatible pointer type
handle.c: In function 'rb_dlhandle_sym':
handle.c:168: warning: passing argument 2 of 'GetProcAddressW' from
incompatible pointer type
handle.c:182: warning: passing argument 2 of 'GetProcAddressW' from
incompatible pointer type
Generating callback.func
Generating cbtable.func
arm-wince-cegcc-gcc -I. -I../.. -I../../. -I../.././ext/dl
-DHAVE_WINDOWS_H -DHAVE_GETLASTERROR -DHAVE_FREELIBRARY
-D_LINUX_SOURCE_COMPAT -I. -g -O2 -fno-defer-pop
-fno-omit-frame-pointer -c dl.c
In
file included from
/exportATA/development/wince/cegcc/bin/../lib/gcc/arm-wince-cegcc/4.1.0/../../../../arm-wince-cegcc/lib/../include/w32api/windows.h:51,
from dl.h:25,
from dl.c:8:
/exportATA/development/wince/cegcc/bin/../lib/gcc/arm-wince-cegcc/4.1.0/../../../../arm-wince-cegcc/lib/../include/w32api/winbase.h:1875:
error: 'OpenFile' redeclared as different kind of symbol
../../rubyio.h:31: error: previous declaration of 'OpenFile' was here
dl.c: In function 'rb_io_to_ptr':
dl.c:554: error: 'fptr' undeclared (first use in this function)
dl.c:554: error: (Each undeclared identifier is reported only once
dl.c:554: error: for each function it appears in.)
make[1]: *** [dl.o] Error 1
make[1]: Leaving directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/dl'
make: *** [all] Error 1
The problem is the existing definition of OpenFile in the CEGCC
system headers; I'm not sure what to do here, we can do a #undefine
OpenFile in rubyio.h and change the function name to something else,
such as new_OpenFile, but I'm unsure how much of an impact that will
have on the rest of Ruby. I think that's an exercise left to a later
date. For now I just removed the ext/dl directory; I don't think this
is an issue unless you are using Ruby to link into libraries under
Windows CE.
ext/socket
compiling socket
make[1]: Entering directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/socket'
arm-wince-cegcc-gcc -I. -I../.. -I../../. -I../.././ext/socket
-DHAVE_ARPA_INET_H -DHAVE_SOCKADDR_STORAGE -DHAVE_NETINET_TCP_H
-DHAVE_INET_NTOA -DHAVE_INET_ATON -DHAVE_GETSERVBYPORT
-DHAVE_TYPE_SOCKLEN_T -DHAVE_SYS_UIO_H -DHAVE_SOCKET -DHAVE_GETHOSTNAME
-I. -D_LINUX_SOURCE_COMPAT -g -O2 -c socket.c
In file included from socket.c:73:
addrinfo.h:162: error: conflicting types for 'gai_strerror'
/exportATA/development/wince/cegcc/bin/../lib/gcc/arm-wince-cegcc/4.1.0/../../../../arm-wince-cegcc/include/netdb.h:461:
error: previous declaration of 'gai_strerror' was here
make[1]: *** [socket.o] Error 1
make[1]: Leaving directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/socket'
make: *** [all] Error 1
Ok, so where is gai_strerror used?...
$ grep gai_strerror ext/socket/*
ext/socket/addrinfo.h:extern char *gai_strerror __P((int));
ext/socket/extconf.rb: (void)gai_strerror(gaierr);
ext/socket/getaddrinfo.c:gai_strerror(ecode)
ext/socket/socket.c: rb_raise(rb_eSocket, "getnameinfo: %s",
gai_strerror(error));
...
...
ext/socket/socket.c: rb_raise(rb_eSocket, "getnameinfo: %s",
gai_strerror(error));
So lets patch that defintion of gai_strerror by undefining
gai_strerror and defining it as something else. Edit ext/socket/addrinfo.h
so that:
extern char *gai_strerror __P((int));
becomes:
#undef gai_strerror
#define gai_strerror new_gai_strerror
extern char *gai_strerror __P((int));
Now let's run make again:
compiling socket
make[1]: Entering directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/socket'
arm-wince-cegcc-gcc -I. -I../.. -I../../. -I../.././ext/socket
-DHAVE_ARPA_INET_H -DHAVE_SOCKADDR_STORAGE -DHAVE_NETINET_TCP_H
-DHAVE_INET_NTOA -DHAVE_INET_ATON -DHAVE_GETSERVBYPORT
-DHAVE_TYPE_SOCKLEN_T -DHAVE_SYS_UIO_H -DHAVE_SOCKET -DHAVE_GETHOSTNAME
-I. -D_LINUX_SOURCE_COMPAT -g -O2 -c getaddrinfo.c
getaddrinfo.c:246: error: static declaration of 'inet_pton' follows
non-static declaration
/exportATA/development/wince/cegcc/bin/../lib/gcc/arm-wince-cegcc/4.1.0/../../../../arm-wince-cegcc/include/arpa/inet.h:60:
error: previous declaration of 'inet_pton' was here
make[1]: *** [getaddrinfo.o] Error 1
make[1]: Leaving directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/socket'
make: *** [all] Error 1
Argh... more previous declerations!. Looking at getaddrinfo.c, line 246 however, shows that
'inet_pton' is only defined here if the compiler flag -DHAVE_INET_PTON
is not set. Seems like we should set that flag and try again - but
don't!... even though inet_pton is defined in the CEGCC headers, there
are no corresponding symbols in the provided libc.a file:
/exportATA/development/wince/cegcc/arm-wince-cegcc/lib $
arm-wince-cegcc-nm libc.a | grep inet
U inet_aton
inet_aton.o:
00000000 T inet_aton
inet_lnaof.o:
00000000 T inet_lnaof
inet_mkadr.o:
00000000 T inet_makeaddr
inet_net.o:
00000000 T inet_network
inet_netof.o:
00000000 T inet_netof
inet_ntoa.o:
00000408 T __MS_inet_addr
000007e4 T __MS_inet_ntoa
00000af4 T inet_addr
00000ab4 T inet_ntoa
U inet_ntoa
So if we just set the compiler flag we'd end up with unresolved
symobls when it came to linking the Ruby binary right at the end (been
there, got the t-shirt!).
We will need to redfine it locally, as we did for addrinfo.c:
So in getaddrinfo.c, change:
inet_pton(af, hostname, pton)
...to:
#undef inet_pton
#define inet_pton new_inet_pton inet_pton(af, hostname, pton)
You'll need to do a similar change change the definition of
inet_ntop to new_inet_ntop in getnameinfo.c:
So in getnameinfo.c, change:
static const char *
inet_ntop(af, addr, numaddr, numaddr_len)
...to:
#undef inet_ntop
#define inet_ntop new_inet_ntop
static const char *
inet_ntop(af, addr, numaddr, numaddr_len)
Final make?
What happens if we run make one last time?...
LIBRUBY_SO_UPDATE=$(LIBRUBY_EXTS)
SETUP=ext/Setup
EXTOBJS=ext/extinit.o ext/bigdecimal/bigdecimal.a ext/digest/digest.a
ext/digest/bubblebabble/bubblebabble.a ext/digest/md5/md5.a
ext/digest/rmd160/rmd160.a ext/digest/sha1/sha1.a
ext/digest/sha2/sha2.a ext/enumerator/enumerator.a ext/etc/etc.a
ext/fcntl/fcntl.a ext/io/wait/wait.a ext/nkf/nkf.a ext/pty/pty.a
ext/racc/cparse/cparse.a ext/sdbm/sdbm.a ext/socket/socket.a
ext/stringio/stringio.a ext/strscan/strscan.a ext/syck/syck.a
ext/thread/thread.a
EXTLDFLAGS=-L'.' -L.
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib
making ruby.exe
make[1]: Entering directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111'
arm-wince-cegcc-gcc -g -O2 -DRUBY_EXPORT -L.
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib -L'.' -L.
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib main.o
ext/extinit.o ext/bigdecimal/bigdecimal.a ext/digest/digest.a
ext/digest/bubblebabble/bubblebabble.a ext/digest/md5/md5.a
ext/digest/rmd160/rmd160.a ext/digest/sha1/sha1.a
ext/digest/sha2/sha2.a ext/enumerator/enumerator.a ext/etc/etc.a
ext/fcntl/fcntl.a ext/io/wait/wait.a ext/nkf/nkf.a ext/pty/pty.a
ext/racc/cparse/cparse.a ext/sdbm/sdbm.a ext/socket/socket.a
ext/stringio/stringio.a ext/strscan/strscan.a ext/syck/syck.a
ext/thread/thread.a -lruby-static -lm
-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib
-I/exportATA/development/wince/cegcc/arm-wince-cegcc/include -o ruby.exe
Info: resolving _CRT_MT by linking to __imp__CRT_MT (auto-import)
Info: resolving __ctype_ptr by linking to __imp___ctype_ptr
(auto-import)
Info: resolving environ by linking to __imp_environ (auto-import)
ext/socket/socket.a(getaddrinfo.o): In function `get_addr':
/exportATA/development/wince/zipped/ruby-1.8.6-p111/ext/socket/getaddrinfo.c:620:
undefined reference to `__h_errno_location'
collect2: ld returned 1 exit status
make[1]: *** [ruby.exe] Error 1
make[1]: Leaving directory
`/exportATA/development/wince/zipped/ruby-1.8.6-p111'
make: *** [all] Error 2
Try as I might, I just cannot figure this one out... I'm pretty
sure
that the socket extension is very, very close to compiling cleanly;
we're missing that one symbol. So, at the moment, you'll need to remove
socket.a for the list of objects. If you do, then you'll get a built
Ruby binary:
$ ls -l ruby.exe
-rwxr-xr-x 1 megatron users 2805351 2008-02-23 15:40 ruby.exe
You can now do a make install and copy the three resultant
folders
(bin, lib and man) to your Pocket PC. Strip the binaries if you wish.
You will also need to copy the three libraries (cegcc.dll,
cegccthrd.dll, libstdc++.dll) from
/exportATA/development/wince/cegcc/arm-wince-cegcc/lib/device to the
\windows directory of your mobile device. Don't forget this step as
nothing you compile with CEGCC will work without these libraries!
Does it work?
Let's find out...

And how about 'irb'?...


I guess that's a yes then! :-)
However...
Issues?
Although the main
Ruby interpreter now seems to work (mostly) without issue, there are
still serious problems remaining that are particular to the Windows CE
environment. The most serious of these is the lack of relative
directory support; this has the effect of forcing all of your 'require'
statements to be fully qualified paths. This means that Rubygems won't
install, severely reducing the usefulness of Ruby on these devices:
See how I have to give the
full path to the setup.rb, and because 'rubygems' is not in the default
location of \ruby\lib\ruby\1.8 it is therefore not found:

Going back to our earlier problems with ext/socket,
we can see now that anything that depends on it is broken..

So far I have managed to get part way through the install of Rubygems,
by performing the following:
copy rubygems-1.0.1/lib/* to /ruby/lib/ruby/1.8
edit rubygems-1.0.1/setup.rb to use full pathnames whereever
os.chdir is called

This then seems to get most of the way through building and installing rubygems, but it fails on our old friend 'require socket'. If we could get that issue sorted, then I think we could take this quite a bit further (I'd love to see Rails and sqlite running!). As it is, it's frustratingly short of being really productive.
Gems - 24th Feb, 2008
With the latest release now having a 'working' socket extension Gems
can now install and run! Yay!


More Extensions - 24th Feb, 2008
Quite a few of the Ruby extensions now build and work...

Have a play with the latest download (240308) and
give it a try.
A working patch for a plain Ruby source tree is coming shortly!
Sockets are working! -
24th Feb, 2008
The functions I patched in ext/socket/ and the simple socket connection
tests from ruby-doc.org actually run!

This bodes extremely well for further, more complicated developments.... watch this space!
Regression Testing -
1st March, 2008
I've been doing a bit of work during the evenings this week - first the
bad news; I just can't get Gem to work at all...
The good bit about gem is that is does actually connect to
rubyforge and download the compressed gem metadata (Marshal.x.y.Z) -
this is confirmed by my web proxy showing the request from the PDA
(both emulated and physical versions).
However the bad bit is not promising at all; on download Ruby works
away for a few seconds and then blows up with a memory allocation
error... I don't think there's a way around this. I'm also having
trouble installing gems locally. Looks like we're going to have to rely
on building from setup.rb's whenever we install a new package with Ruby
on Arm-Wince-CEGCC.
I have a feeling this memory allocation issue is going to bite me
again. On a related note, a colleague at work is playing around with
PythonCE + Django on the same hardware as me, and despite the ready
built PythonCE binary, he's also seeing very, very tight tolerances in
the amount of free memory. I wish Windows CE itself didn't eat 20+Mb of
the standard 64Mb :-(
I almost got a working Rails installation up and running - it only
needs a few relative path changes to work from a storage card location
(I'm working on the assumption that the ~10mb Ruby base installation
would go in the built-in flash of a PDA, but a Rails instance, being
larger at ~20-30mb would likely sit on a CF or SD card).
These changes are relatively minor, and I'll post a patch in the files
section for anyone who wants to try it - there are
errors preventing me from going any further at the moment. So I've
decided to go back and see if I can get the whole regression test suite
from the Ruby source code working.. when cross compiling those tests
can't be run - so we need to run them from Windows CE instead.. again
the relative path problem strikes!
It's not looking too bad in terms of overall compatability for the Ruby
Arm-Wince-CEGCC platform; a lot
of the tests run without error. But I think some of those that do error
out could well be causing the Gem and Rails problems I'm seeing. I'll
be creating an 'overlay' archive that you can unzip over your Windows
CE Ruby install and run the regression tests.
I'm also looking at building a shared libary version of Ruby in order
to reduce memory use; the binary is a bit fat right now. So far I've
managed to build a .dll version of zlib, and I have made some
progress with OpenSSL.. that should help. I'll also listen to any
suggestions for which extensions to build and which to leave out -
socket, thread, stringio, zlib and openssl are looking like the main
ones to retain for now.
Shared Libraries
& Ext modules - 2nd March, 2008
I haven't been able to get the Ruby configure or makefiles to do it
automatically for me, but it does look like it is possible to build the
extensions and even libruby as dynamic DLL's, so the only whatever is
'require'-ed will be loaded. This should help greatly in reduced memory
use.
Anyway, if you configure the source code as below:
CC=arm-wince-cegcc-gcc \
CPP=arm-wince-cegcc-cpp \
CFLAGS="-Os -g" \
LIBS="-lcegcc.dll" \
LDFLAGS="-L/exportATA/development/wince/cegcc/arm-wince-cegcc/lib" \
./configure \
--disable-ipv6 \
--host=arm-wince-cegcc \
--enable-shared \
--prefix=/ruby \
-C
.. and also edit your ext/Setup to choose which modules you
want, run make as normal.
Now, you'll have to edit each ext/MODULE/Makefile to remove the -fPIC
flag and change the LDSHARED value from:
LDSHARED = "ld"
to:
LDSHARED = arm-wince-cegcc-gcc --shared
This will cause the arm-wince-cegcc-gcc compiler to enable
several
additional macros and produce a Windows CE compatible DLL. You will
need to do this for each ext module you are using - sorry I haven't
figured out how to get configure to produce valid ext Makefiles by
itself yet.
You can check you've got a valid dll by changing to your main Ruby
source direct and then to ".ext/arm-cegcc/", run "file *.so" and you'll
see something like:
/ruby-1.8.6-p111/.ext/arm-cegcc $ file *.so
bigdecimal.so: MS-DOS executable PE for MS Windows (DLL) 32-bit
digest.so: MS-DOS executable PE for MS Windows (DLL) 32-bit
enumerator.so: MS-DOS executable PE for MS Windows 32-bit
fcntl.so: MS-DOS executable PE for MS Windows 32-bit
nkf.so: MS-DOS executable PE for MS Windows 32-bit
sdbm.so: MS-DOS executable PE for MS Windows 32-bit
syck.so: MS-DOS executable PE for MS Windows 32-bit
thread.so: MS-DOS executable PE for MS Windows (DLL) 32-bit
You can see in the above example the difference between a
normal shared object and the DLL version.
Links
http://www.cygwin.com - Cygwin,
Unix-like environment and tools for Windows.
http://cegcc.sourceforge.net
- CEGCC Project, ARM+WinCE cross development toolchain.
http://www.ruby-lang.org -
Homepage and downloads for the Ruby programming language.
http://www.ruby-forum.org -
Discussion and news forums for Ruby.
Download
Shell script which unpacks a clean Ruby 1.8.6 source tree and applies
my WinCE/ARM patch
Download
My last patch against a clean Ruby 1.8.6-p114 source tree.
Download Script
to remove any references to -fPIC after configuring the Ruby 1.8.6-p114
source.
Download Attempt to
build shared binaries from the patched Ruby 1.8.6-p114 source.
Download Attempt to
build static binaries from the patched Ruby 1.8.6-p114 source.
Cross compilation command
aliases
24th Feb
2008 - Ruby 1.8.6-p111 for WinCE/ARM -O3 Optimised binaries for
Windows CE/ARM - includes complete working Gem install.
PocketConsole, DLL, Registry
tool and instructions for setting up a console on Windows CE
Rubygems-1.0.1 initial setup.rb file
- for those who want to try to get it working.