Hi all,

(David, please take a look below)

I've sit down tonight and got gnustep-base to run under Android. The
hardest part is having to manually load the dynamic libraries; apparently
Android's android.app.NativeActivity is dumb enough to fail miserably when
it has to (oh shock and horror) load a library that the .so containing
native depends on.

(For those who don't know, Android applications cannot be written purely in
native code. Even NativeActivity class, introduced relatively late and used
primarily for games, is code written in Java that loads a shared object
library and calls native code at appropriate times.)

Native code on Android in any non-console application is delivered as an
.so. If it shows up on screen, it's not a standalone ELF executable. Simple
as that. Hence the modus operandi is this: Application is always written in
Java. Java code uses JNI to load an .so. Java code then calls C functions
as appropriate. Native code may call back into Java.

-- Where was I stuck?

When it comes to usual GNU/Linux systems, libobjc2 is a good behaving
citizen that specifies soname in the form of "libobjc.so.4.6"; when it
comes to Android systems, libgnustep-base is a better behaving citizen that
specifies so name in the form of "libgnustep-base.so". On regular systems,
end user may not notice, as both are shipped as "libXYZ.so.A.B" and
symlinked into "libXYZ.so". libobjc2 follows the recommendations, though,
and libgnustep-base does not.

Doesn't really matter on Android, as the requirements are completely
opposite; if you put a binary in "...apkroot/lib/armeabi" and it doesn't
have the extension .so, it won't get shipped. Dynamic loader will choke
when trying to load libgnustep-base.so which references to libobjc2 based
on its soname; same for libAPPNAME.so.


David:

The hack that I found online, where I edit libgnustep-base.so and
libAPPNAME.so to replace "libobjc.so.4.6" with "libobjc.so\0\0\0\0" is just
that - a hack.

Can you look into the best way to force CMake to pass -soname libobjc.so to
the linker, but just on Android? I have a CMake toolchain file for Android,
but I'm unsure how to specify that the version number should not be
suffixed on Android.


-- So, what does the .apk that I have do?

Nothing much:
  NSString * hello = @"hello";
  LOGI([hello UTF8String]);
which is just enough to see the output in Android's "logcat".

-- Where is the updated script to build gnustep-base for Android, and where
is the demo application?

In private Bitbucket repositories. While I'm looking forward to approval to
release relevant code from my employer, I'll stay cautious. When/if I get
the approval, I'll push the updated code into publicly available
repositories.

Publicly available code:
  http://bitbucket.org/ivucica/gnustep-android
  http://bitbucket.org/ivucica/thegrandexperiment

First repository contains non-up-to-date code to fetch Android SDK and NDK,
create standalone toolchain, fetch gnustep-make, gnustep-base and libobjc2,
patch gnustep-base appropriately, build and "install" libobjc2,
gnustep-make and gnustep-base.

Second repository demonstrates how to build an Android application without
having to use the Android build system. Sadly, it has a lot of hardcoded
paths, and Windows paths at that. Updated version still has a lot of
hardcoded paths, but at least they're under Linux (and match the
.../gnustep-android paths).

-- What did I have to do?

I'll describe the updates to gnustep-android repo, in case approval doesn't
come or someone wants to upstream the changes.

First, since the two patches that I had were not applying cleanly, I
removed them. Maybe relevant fixes, relating to 'daylight' and 'dladdr
branch in objc-load code' are upstream already.

Second, -base's SSL subdirectory was being used even when --disable-openssl
was passed. Worse, when its configure was called, it did not receive the
same flags as the root configure, so it was throwing errors around. This
has been fixed by introducing ENABLE_OPENSSL variable in a couple of places
(as opposed to HAVE_OPENSSL, since this relates solely to flag being
passed; it is my understanding that further detection is being done in the
SSL/ directory's configure) and slightly cleaning up the relevant part of
configure.ac. <- This introduced patch numbered 03.

Third, -base's make install failed because gdomap could not be built. As it
is useless for Android anyway, in case Android is being targeted
(GNUSTEP_TAGET_OS linux-androideabi), no longer is subproject Tools
appended to the appropriate library. Neither are NSTimeZones, Resources and
Tests; solely because it makes little sense to build anything relating to
resources or to run tests while cross compiling. On Android, we'll have to
deal with any resource loading in a different way, anyway, so whatever is
in Resources/ and NSTimeZones/ can be skipped for now.  <- This introduced
patch numbered 04.

Fourth, to make thegrandexperiment work, I've switched to android-14.
(android-8 doesn't include EGL/ headers, it seems.)

Those were changes to gnustep-android. What changed in thegrandexperiment?

Linux code path was added to Makefile. If TEST_OBJC=true, Makefile uses
objcopy with strip argument to copy libobjc.so.4.6,
libTheGrandExperiment.so and libgnustep-make.so into apk/lib/armeabi. Tool
called "rpl" is used to replace .4.6 with \0. Class TGENativeActivity,
subclass of android.app.NativeActivity is introduced, empty except for
static {} section to load libraries objc, gnustep-base and
TheGrandExperiment, so everything is ready by the time
android.app.NativeActivity kicks off.


-- What next?

These are all changes that'd be dumb to replicate, so I'm looking forward
to hearing from whoever I need to get approval from. Everything was done in
my spare time, so I hope there won't be any issues. It's worth noting that
patches for gnustep-base itself are rather small.

On Sun, Dec 29, 2013 at 12:56 PM, David Chisnall <thera...@sucs.org> wrote:

> Hello everyone,
>
> I'm trying to cross-compile GNUstep, and since I'm sure I'm not the first
> person to try this, I wondered if anyone had written up how to do it?  I am
> trying to build from FreeBSD/amd64 for FreeBSD/MIPS64.  I have a
> cross-compiler and sysroot setup.  Building the runtime was trivial - just
> point cmake at the cross-compile toolchain file - what do I need to do for
> Make / base so that:
>
> - It knows that I don't actually want -make on the target platform.
> - I get an installed version somewhere on my local machine that I can copy
> to a different location on the remote
> - All of the correct cross-compile flags are passed to the compiler
>
> I think Ivan has been through all of this recently for Android?
>
> David
>
> --
> This email complies with ISO 3103
>
>
> _______________________________________________
> Gnustep-dev mailing list
> Gnustep-dev@gnu.org
> https://lists.gnu.org/mailman/listinfo/gnustep-dev
>



-- 
Ivan Vučica
i...@vucica.net
_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev

Reply via email to