I did try to create a nimrod-on-android test case and failed.
Initially the process seems quite simple:
If anybody is interested you can grab what I've managed so far from https://github.com/gradha/nimrod-on-android.
First I examined the different build mechanism. I was trying to use the fancy multi-library deployment (see https://github.com/gradha/nimrod-on-android/commit/2b36eae62c84e6cd3381b4d1df4578201afb5365) which would allow the jni generated code to simply link a nimrod library generated from another directory and the example was crashing. Hoping it was not the linking process I moved everything to the level of the hello-jni.c code (see https://github.com/gradha/nimrod-on-android/commit/3a2f93d66eef97ae55ca7cb45d09aaa2d9b5bb93) but still no dice.
Not knowing anything about nimrod or the android ndk and in possession of a fearless hammer I started to hack the nimrod generated code by putting return statements in the NimMain() code. Through careful putting and advancing the return I reached the conclusion that the culprit of the crash is somewhere below NimMain()->systemInit->Initgc_4011->Init_29694->Alloc0_2584.
At this point I lost interest and didn't feel like continuing. I don't think I'll come back to this any time soon (at the moment I'm also exploring other mobile cross-plaform toolkits) but there's the code if any taker wants to continue debugging the nimrod code.
One relevant note to the possible failure are the numerous warnings about pointer size being generated during the ndk-build phase. You can see them at https://github.com/gradha/nimrod-on-android/wiki/Compilation-log. I was testing this on an HTC Legend handset, which works fine when nimrod is not invoked.
One relevant note to the possible failure are the numerous warnings about pointer size being generated during the ndk-build phase.
Well if the generated C code got the pointer size wrong, it's no wonder it crashes ... According to wikipedia a HTC Legend has a Qualcomm MSM 7227 600 MHz processor... What does uname -a say? I'm sure we can get it to work.
You could also try Nimrod with Boehm's GC via --gc:boehm.
Using Boehm's GC didn't work. uname -a can't be run on these phones because they are not rooted. However, I was able to access some /proc info:
HTC Legend:
$ cat /proc/version Linux version 2.6.29-e3993620 (htc-kernel@and18-2) (gcc version 4.4.0 (GCC) ) #1 PREEMPT Mon Mar 8 13:00:40 CST 2010 $ cat /proc/cpuinfo Processor : ARMv6-compatible processor rev 5 (v6l) BogoMIPS : 599.65 Features : swp half thumb fastmult vfp edsp java CPU implementer : 0x41 CPU architecture: 6TEJ CPU variant : 0x1 CPU part : 0xb36 CPU revision : 5 Hardware : legend Revision : 0080 Serial : 0000000000000000
Google Nexus One:
$ cat /proc/version Linux version 2.6.35.7-59465-g42bad32 ([email protected]) (gcc version 4.4.3 (GCC) ) #1 PREEMPT Thu Apr 21 11:13:39 PDT 2011 $ cat /proc/cpuinfo Processor : ARMv7 Processor rev 2 (v7l) BogoMIPS : 162.54 Features : swp half thumb fastmult vfp edsp thumbee neon CPU implementer : 0x51 CPU architecture: 7 CPU variant : 0x0 CPU part : 0x00f CPU revision : 2 Hardware : mahimahi Revision : 0081 Serial : 0000000000000000
One emulator machine I had:
# cat /proc/version Linux version 2.6.29-00261-g0097074 ([email protected]) (gcc version 4.4.0 (GCC) ) #14 Tue Feb 2 15:49:02 PST 2010 # cat /proc/cpuinfo Processor : ARM926EJ-S rev 5 (v5l) BogoMIPS : 67.78 Features : swp half thumb fastmult vfp edsp java CPU implementer : 0x41 CPU architecture: 5TEJ CPU variant : 0x0 CPU part : 0x926 CPU revision : 5 Hardware : Goldfish Revision : 0000 Serial : 0000000000000000
Not sure if any of this is of use. Maybe a printf("...", sizeof(blah)) to find out the problem with the casts?
I just attempted to get it working and succeeded.
I still get those warnings that you got even if I use --cpu:arm however. I have forked your repo and commited my changes here: http://github.com/dom96/nimrod-on-android
It works fine for me in the emulator. Did not yet test on real hardware but I assume it would work too.
Let me know if you can get it working.
Here is a screenshot of it running in an emulator:
Ah! Now the pieces fall together. dom96's repo still crashed for me, but reading through the readme I noticed this was all built in a linux environment. And just now you suggested adding --os:linux, which is the missing piece. I'm running on macosx, so adding that switch to the nimrod compilation step solves the crashes and both my test case and dom96's work fine.
Some time later I'll continue the example and update the repo properly. Thanks to both.
Sigh, problems seem to haunt me. This time I've reached the point where I was implementing the JNI interface, which is very easy for simple primitive types since there is practically no object creation/destruction involved.
So I created the JNI bridge for myAdd() and the function gets called, but instead of returning the expected value always the first parameter is returned. Here's the C bridge code:
char buf[256]; const jint ret = myAdd(a, b); sprintf(buf, "a %d + b %d = ret %d", a, b, ret); __android_log_write(ANDROID_LOG_DEBUG, TAG, buf); return ret;
The jint is an alias for int. I don't think this would be a problem since I also used ints for the iOS example despite the type being actually long long int on the nimrod side. Just in case using jlong (the 64 bit version) doesn't change the result. Thanks to the android logging code I get on the console:
D/native C( 2036): Nimrod initialised D/native C( 2036): a 4 + b 18 = ret 4
Which suggest the NimMain() function is being called, and the log shows the parameters being passed correctly from java to C, only the myAdd() call returns a weird value.
I took the backend.nim from dom96 which instead calles the myAdd() inside the nimrod code and returns everything as a string, and calling that works fine, the nimrod string contains the expected value. Which leads me to believe that the nimrod code is fine, but the return value is somehow getting mangled somewhere in the C bridge. Any ideas?
I've put this new version on a branch at https://github.com/gradha/nimrod-on-android/tree/incorrect_nimrod_logic
typedef long long int NI;
typedef unsigned long long int NU;
As that's only true on a 64bit system, which Android is not... Again cross compilation requires --os:linux --cpu:arm: http://build.nimrod-code.org/docs/nimrodc.html#cross-compilationExcellent, nice job gradha :D
Are you going to develop iOS and Android apps in Nimrod now? :)
Highly unlikely. I still want to look into other potential platforms like haxe or mono, and the latter seems to get all the points for already being there, proven, and nice to work with (that's why I'm going to test that last, to avoid me spoiling the fun of testing others).
On the other hand building a JNI Java interface for Nimrod looks like an interesting project, especially if you factor in concurrency issues (what about java threads calling reentrant nimrod code from outside and so on).