Talk:Compiling for Android
Bob the Hamster (talk) 22:01, 1 June 2013 (PDT): I am a bit confused by the freebasic instructions. I understand that I need to create a config.mk and put some stuff in it. I don't know what the toolchain is, except that the android/compile-using-toolchain.sh script seems to populate it, but I have not yet gotten to the step where I try that. Why /tmp ? That seems like a really strange place to put anything.
Bob the Hamster (talk) 22:09, 1 June 2013 (PDT): My config.mk looks like this:
ENABLE_PREFIX=1 prefix=/home/james/misc/fbc-0.90-android PATH:=/tmp/android-toolchain/bin:$(PATH) TARGET_PREFIX=arm-linux-androideabi-
but when I do make compiler it says:
james@rhinoctopus:~/src/misc/fbc-tmc$ make compiler makefile:414: target `src/rtlib/arm-linux-androideabi-' given more than once in the same rule. makefile:414: target `obj' given more than once in the same rule. makefile:414: target `freebasic' given more than once in the same rule. makefile:445: warning: overriding commands for target `lib/arm-linux-androideabi-' makefile:417: warning: ignoring old commands for target `lib/arm-linux-androideabi-' makefile:448: warning: overriding commands for target `lib/arm-linux-androideabi-' makefile:445: warning: ignoring old commands for target `lib/arm-linux-androideabi-' makefile:451: warning: overriding commands for target `lib/arm-linux-androideabi-' makefile:448: warning: ignoring old commands for target `lib/arm-linux-androideabi-' makefile:459: warning: overriding commands for target `lib/arm-linux-androideabi-' makefile:451: warning: ignoring old commands for target `lib/arm-linux-androideabi-' makefile:462: *** multiple target patterns. Stop.
I assume this is just because I don't know jack about makefiles :)
TMC (talk): That was quite puzzling, but I've discovered that it must be because you have a space at the end of the TARGET_PREFIX line. I sure hate makefiles.
The standalone NDK toolchain is the bare essentials copied from the NDK: tools, headers and libraries to target a single specific arch+android version using a specific GCC/Clang version. I simply put it in /tmp because that's what the NDK docs suggested. Probably because you install multiple of them for your different targets then can delete when done. My own config.mk:
PATH:=/tmp/android-toolchain/bin:$(PATH) TARGET_PREFIX=arm-linux-androideabi- ENABLE_PREFIX=1 CFLAGS := -Wfatal-errors -O0 -g prefix=/home/ralph/local/fbc-0.90-android V=1
Looking closer at the makefile, I see $prefix is the install location, so you definitely want to specify that, since it's not a normal build of FB; though you could build non-crosscompiling versions of rtlib and fbgfx libraries and install those too and it should work
Bob the Hamster (talk) 12:26, 2 June 2013 (PDT): Yup! You are right. That one extra space was throwing it off.
debuginfo crash
Bob the Hamster (talk) 13:04, 2 June 2013 (PDT): I was able to get through the whole compiling process, and ended up with an apk, but when I ran it on the device, it crashed with a file-not-found in debuginfo http://pastebin.com/raw.php?i=gxyATZTg
TMC (talk): What is line 352 in common.rbas.bas for you? For me, with no modifications to common.rbas, it is "sizeerror = -1". I don't see which line in debuginfo could throw that error, unless it's possible for a "file not found" error to be printed when attempting to access a file which has already been successfully opened...
You could try using ndk-gdb (instructions on Android Port to see where exactly in libfb the error is thrown from. Also it's a mystery how debuginfo is being called before startup, so the backtrace will be very interesting.
Bob the Hamster (talk) 07:29, 3 June 2013 (PDT): Line 352 in common.rbas.bas is the same for me as for you. Nothing looks unusual in that file. I tried ndk-debug but the SDL logo flickers on the device's screen and the crashes before gdb has a chance to connect to it: http://pastebin.com/raw.php?i=BcEzMxKu
TMC (talk): Having another look at the generated C and looking through the rtlib source, that error message still looks impossible. There is no place where line number 352 is passed to anything, unless its line 352 in a different file. Maybe you changed something and forgot to recompile using scons before invoking build.sh? Also once scons stopped because of an error which I failed to notice but build.sh still built successfully, which was quite confusing.
I suggest adding "sleep(3000)" at the top of debuginfo to allow gdb time to attach. The ndk-gdb script contains a wait of several seconds.
Bob the Hamster (talk) 07:17, 4 June 2013 (PDT): Oh! Duh! I did have a change that I had not realized. I had forgotten that I was messing around with CompatibilityHacksAdditionalPreloadedSharedLibraries in my AndroidAppSettings.cfg
Although now I am confused by other problems. I saw the same "undefined reference to 'SDL_main" error, but when I messed with my symlinks I seem to have screwed up everything, and compile-using-toolchain.sh doesn't seem to create any files in android/tmp I am going to start over.
Bob the Hamster (talk) 07:53, 4 June 2013 (PDT): Yay! I followed the instructions more carefully, and now I can build a working apk! I had failed to notice the difference between scons android=1 and scons android-source=1
TMC (talk): Great :). Were you trying to preload libapplication.so? I could see that leading to problems, though I still don't understand how the error message could have been caused.
The files in android/tmp are created by android_source_files in ohrbuild.py, which really ought to be replaced with a better system. Either calling the standalone toolchain from scons, or continuing with a two phase build with our own Android.mk to replace the unsuitable one in the SDL port.
Just like on all other platforms, unless you compile with debug=0 (which we do for Windows nightly builds but not Mac or Linux), when FB encounters an error it will immediately kill the program (I really ought to install a hook in the rtlib to handle this better!). That includes when OPEN fails, which is pretty likely on Android because of all the paths that need updating.
Ubuntu
S'orlok Reaves (talk): Just thought I might add that, for Ubuntu users, Free Basic won't compile unless you install lib32ncurses5-dev. I'm not sure why Free Basic complained about this particular library; for everything else, "libWhatever-dev" seemed to work.
TMC (talk): Right, that's at the "make compiler" step. The fbc compiler itself is a 32 bit binary (although there is a 64 bit branch of FB, which didn't yet work last time I checked). The rtlib of course shouldn't depend on anything outside the standalone toolchain.
Symlinks
S'orlok Reaves (talk): I'm getting "undefined reference to 'SDL_main'" when I try to run ./build.sh inside the sdl-android directory. Is anyone else getting this?
S'orlok Reaves (talk): Ok, I figured it out. The wiki text "Create a symlink from sdl-android/project/jni/application/src to sdl-android/project/jni/application/ohrrpgce" was somewhat inaccurate. You actually want to do something like this:
cd sdl-android ln -s ohrrpgce project/jni/application/src
...because build.sh expects the link to point locally to "ohrrpgce". If you point it to anything else (subfolder, absolute path, etc.) it will fail.
TMC (talk): Yeah, I found the arguments to ln to be quite unintuitive. ln and ln -s work quite differently: ln (for hardlinks) takes a normal file path, while ln -s takes a string which is put into the symlink and is relative to the symlink's location, not the current directory. Some versions of GNU ln takes an -r argument (relative) to make the ln -s destination relative to the current directory instead.
S'orlok Reaves (talk): I would recommend that new developers generally avoid hard symlinks; otherwise, a stray "rm" command can take out the OHR and Free Basic directories as well. At least for the last step (linking the current SDL project to "src") you should definitely use a soft link unless you're 100% sure you want a hard link. (Note that I used only soft links for compiling).
Speculation
S'orlok Reaves (talk): This is just wild speculation, but it occurs to me that the Raspberry Pi uses an ARM chip and is known to run SDL apps. Do you think the same basic steps here would work for that? (Obviously I would have to create my own toolchain instead of using the NDK's version.) In particular, I'm wondering if, given a properly configured toolchain, FB should be able to "make compiler" and "make rtlib". Any thoughts?
TMC (talk): That definitely should be possible! However I see lots of little changes are needed. Have you got a Raspberry Pi? I'd love to see it happen.
AFAIK android uses identical ABIs to other ELF unix OSes on the same CPU architectures (though I get the hint that there may be slight differences in the linker due to some platforms not following the standards to the letter).
My changes to both FB and the OHR conflate Android and ARM in several places. You would want to compile both for a GNU/Linux target instead of Android (if you run a normal GNU/Linux distrib with ncurses and X11 on the RPi). SConscript needs several changes in addition to the ones I just made. If SDL on the RPi uses the frame buffer, then you may not want to link with the X11 libs (actually libfb still links to X11 by default, unless you add -DDISABLE_X11 to config.mk). And it'll need to know where to find the FB libs (it looks like the Raspberry Pi toolchain uses a platform triple of arm-bcm2708hardfp-linux-gnueabi, so you'll probably edit SConscript where I hardcoded arm-linux-androideabi). Looking through my changes to FB, it looks like the only thing which needs changing for GNU/Linux on ARM is to edit rtlib/static/fbrt0.c to use __attribute__((constructor)). fbc should actually be fine for cross compiling to any 32 bit target as long as it's invoked with "-arch arm" (well not quite true: it assumes that it knows how all structures are laid out in memory (that they are the same as laid out by GCC on x86... I'm surprised this hasn't blown up on ARM!)
Look at compile-using-toolchain.sh for how to invoke scons (you'd build Game/Custom directly using scons). You'd probably also need to add the directory containing a build of libSDL.so (and libSDL_mixer.so (or use music=silence)) cross-compiled to the Raspberry Pi to the CXXLINKFLAGS variable in SConscript (we ought to set the standard LDFLAGS variable instead).
S'orlok Reaves (talk): I've got one coming in the mail ---and I noticed you separated the Android/ARM targets in a recent commit, thanks! I'll give it a whirl once my device arrives.
TMC (talk): Cool. I might get around to some other clean up before then. Those SConscript changes were just one thing needed.
Hacking my way through the RPi
S'orlok Reaves (talk): So I've started working on cross-compiling for Raspberry PI. I'm stuck on the "make rtlib" step of FreeBasic (I'll work through it more later, but I figured I've reached a stopping point for tonight so might as well document it.)
First, I installed crosstools-ng, which is by far the most common suggestion for setting up a toolchain. I followed this post for the most part: http://www.kitware.com/blog/home/post/426
Then, I ssh-ed into the RPi and installed libSDL1.2-dev, and all related libraries. Then I did this:
cd ~/opt/rpi_sync rsync -rl pi@192.168.1.110:/usr .
Following that, I checked out the FreeBasic repo listed above and used this config.mk file:
ENABLE_PREFIX=1 prefix=/home/sethhetu/opt/fbc-0.90-rpi PATH:=/home/sethhetu/opt/x-tools/arm-unknown-linux-gnueabi/bin:$(PATH) CFLAGS := -I/home/sethhetu/opt/rpi_sync/usr/include -I/home/sethhetu/opt/rpi_sync/usr/include/arm-linux-gnueabihf TARGET_PREFIX=arm-unknown-linux-gnueabi- V=1
Note that CFLAGS; I was guessing that this would allow me to use the same headers on both the RPi and my laptop. This is just a guess!
At that point, I ran:
make compiler
It ran to completion, then:
make rtlib TARGET=arm-unknown-linux-gnueabi
It fails with:
arm-unknown-linux-gnueabi-gcc -Wall -Werror-implicit-function-declaration -I/home/sethhetu/opt/rpi_sync/usr/include -I/home/sethhetu/opt/rpi_sync/usr/include/arm-linux-gnueabihf -c src/rtlib/linux/sys_portio.c -o src/rtlib/arm-unknown-linux-gnueabi-obj/sys_portio.o src/rtlib/linux/sys_portio.c: In function 'fb_hIn': src/rtlib/linux/sys_portio.c:11:2: error: impossible constraint in 'asm'
The line in question:
__asm__ volatile ("inb %1, %0" : "=a" (value) : "d" (port));
Here's where I'm stumped. If it was a header-file error, I wouldn't be surprised. But it's a c file, and involves the correct toolchain item (arm-unknown-linux-gnueabi-gcc). And the same FreeBasic repo compiled fine for Android with a similar config.mk (but no CFLAGS in this case).
Anyway, I'll debug more this weekend. Any suggestions would be appreciated.
I hadn't noticed that there was asm in use there. To do things properly, we'll want to move that stuff into an x86-specific file, and also provide an ARM implementation of port IO. I assume that anyone using a RPi for hardware hacking and using FB will want ARM implementations of that. I don't know anything about that stuff. But it apears that ARM doesn't have separate IO instructions. Someone said:
The ARM architecture doesn't specify a separate I/O space -- everything is memory-mapped, so: 1) There are no dedicated (fast-path) I/O instructions -- load and store is all you get.
For example see here for an example of accessing the RPi GPIO pins using memory mapping. Well, I'll ask on the FB forums, there are people there who care about that.
Anyway, just comment out that assembly. If you look at rtlib/android/sys_portio.c you'll see the functions throw errors.
S'orlok Reaves (talk): Just adding this brief tidbit; the Android-compiled version has:
arm-linux-androideabi-gcc -DENABLE_MT -Wall -Werror-implicit-function-declaration -DDISABLE_FFI -DDISABLE_X11 -DDISABLE_NCURSES -Wfatal-errors -O2 -c src/rtlib/android/sys_portio.c -o src/rtlib/arm-linux-androideabi-objmt/sys_portio.o
...which contains:
int fb_hIn( unsigned short port ) { return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); }
...etc. I'm sure you (TMC) know about this; I'm just adding it for clarity's sake to anyone else reading along.
No time to work on this today, but I'll probably use FB_RTERROR_ILLEGALFUNCTIONCALL in the linux/sys_portio.c when I get a chance.
Edit: Whoops, I should really read the Talk page before posting; the previous post by TMC already has all of this. Thanks for the link on I/O mapping; it's informative!