November 26, 2013
On Tuesday, 26 November 2013 at 09:53:07 UTC, Chris wrote:
> On Monday, 25 November 2013 at 22:32:26 UTC, Joakim wrote:
>> Next, getting this minimal app running on Android/x86.  It turns out there is some support for building executables directly in the Android NDK, just undocumented, though the docs are fairly bad generally.
Whoo, I just got the above "hello world" app to run on Android/x86 4.3! :D I just compiled the object file with dmd patched to take out _d_dso_registry and using the invocation above, then linked it with the gold linker, Android libraries, and flags that the Android NDK uses, and ran it from a terminal in an Android/x86 VM.  I was not looking forward to debugging arcane ABI issues and it looks like I may not have to. :) I think I'll just use this pure native route to port druntime for now.

> Interesting. Johannes mentioned that the main app should always be in Java so it goes through Dalvik. I've done some JNI-D stuff already (only a proof-of-concept command line app though). I wonder what's the best way of porting D to mobile OS's (mainly Android and iOS).
That is what the docs say if you want to build a native Android app, presumably that you distribute through the Play Store.  But you can always build a native app for your own local dev build of Android, at least for porting purposes.

But look at the test-libstdc++ sample app in the NDK: they actually build it as an executable, not a shared library.  I haven't tested yet if that's a mistake or if it will actually work.  In other words, I don't know if they enforce the shared library approach, whether technically or through some Play Store certification process, but it certainly is the officially blessed approach.

What JNI-D stuff have you tried and on what platform, linux/x86?  I'll try the shared library approach on Android at some point and report back.
November 26, 2013
On Tuesday, 26 November 2013 at 11:22:59 UTC, Joakim wrote:
> That is what the docs say if you want to build a native Android app, presumably that you distribute through the Play Store.  But you can always build a native app for your own local dev build of Android, at least for porting purposes.
Sorry, that should be "native executable" in the second instance, ie it doesn't have to be a shared library if you're just deploying it locally.
November 26, 2013
Am Tue, 26 Nov 2013 12:36:19 +0100
schrieb "Joakim" <joakim@airpost.net>:

> On Tuesday, 26 November 2013 at 11:22:59 UTC, Joakim wrote:
> > That is what the docs say if you want to build a native Android app, presumably that you distribute through the Play Store. But you can always build a native app for your own local dev build of Android, at least for porting purposes.
> Sorry, that should be "native executable" in the second instance, ie it doesn't have to be a shared library if you're just deploying it locally.

Native apps are working, just not officially supported. I actually had a native Hello World working on ARM/Android with GDC, however fixing bugs related to native apps usually isn't high priority on Android.

This bug for example wasn't fixed back then and was a showstopper: http://code.google.com/p/android/issues/detail?id=28598

Last time I looked pure native apps couldn't use the GUI though, has that changed?
November 26, 2013
On Tuesday, 26 November 2013 at 17:12:38 UTC, Johannes Pfau wrote:
> Native apps are working, just not officially supported. I actually had
> a native Hello World working on ARM/Android with GDC, however fixing
> bugs related to native apps usually isn't high priority on Android.
>
> This bug for example wasn't fixed back then and was a showstopper:
> http://code.google.com/p/android/issues/detail?id=28598
I don't see how that was a showstopper when you could avoid it simply by using the right flags, as noted in the penultimate comment there.  Also, I get the impression that the build system makefiles for Android itself are pretty much the same as the NDK, so Android would have some pretty serious problems if they didn't get their toolchain for building native system, ie non-java, processes working right. ;)

> Last time I looked pure native apps couldn't use the GUI though, has
> that changed?
Depends what you mean.  The NDK has always been pitched at game devs, so you can't call the Android UI components directly from native code AFAIK.  But you could use OpenGL ES 2.0 from Android 2.0 and employ EGL with a pure native shared library app since Android 2.3 in 2010, so you could employ your own OpenGL-based GUI toolkit for a long time:

http://mobilepearls.com/labs/native-android-api/ndk/docs/STABLE-APIS.html

And you could always use JNI to do your GUI in java and number-crunching in C/C++, but yeah, that's not pure native.
November 27, 2013
On Tuesday, 26 November 2013 at 11:22:59 UTC, Joakim wrote:
>
> What JNI-D stuff have you tried and on what platform, linux/x86?  I'll try the shared library approach on Android at some point and report back.

If I remember correctly, I did something like this (think it was on OS X):

1. Create D library (seems to be necessary?)
dmd -lib hello.d -oflibhelloD

2. Compile (do not link)
gcc -c hello.c -o helloC.o // Calls D code

3. JNI (compile)
gcc -c -I/path/to/Java/Headers Test.c -o Test.o // JNI file (calls hello.c)

4. Create library.
gcc -dynamiclib -o libTest.jnilib -lphobos2 -lhelloD Test.o helloC.o

And it worked. I don't know, if step 2. is necessary at all.

I've also been able to successfully combine Python and D, so that the D module could be loaded and used by Python like any other module. I could also link D and Objective-C. But that was all on Desktop (Mac OS X and Linux). I haven't tried it for Android or iOS yet.

December 01, 2013
On Wednesday, 27 November 2013 at 13:52:17 UTC, Chris wrote:
> On Tuesday, 26 November 2013 at 11:22:59 UTC, Joakim wrote:
>>
>> What JNI-D stuff have you tried and on what platform, linux/x86?  I'll try the shared library approach on Android at some point and report back.
>
> If I remember correctly, I did something like this (think it was on OS X):
>
> 1. Create D library (seems to be necessary?)
> dmd -lib hello.d -oflibhelloD
>
> 2. Compile (do not link)
> gcc -c hello.c -o helloC.o // Calls D code
>
> 3. JNI (compile)
> gcc -c -I/path/to/Java/Headers Test.c -o Test.o // JNI file (calls hello.c)
>
> 4. Create library.
> gcc -dynamiclib -o libTest.jnilib -lphobos2 -lhelloD Test.o helloC.o
>
> And it worked. I don't know, if step 2. is necessary at all.
>
> I've also been able to successfully combine Python and D, so that the D module could be loaded and used by Python like any other module. I could also link D and Objective-C. But that was all on Desktop (Mac OS X and Linux). I haven't tried it for Android or iOS yet.

Hmm, that seems pretty convoluted, hopefully it won't be as bad on Android.

I've started porting core.stdc from druntime to Android, so far, so good.  One oddity I've run into is that stderr doesn't work properly on half of the existing OS platforms.  Take this test file:
//test.d
import core.stdc.stdio;

extern (C) int main() { fputs("doing this for real?", stderr); return 0;}

It doesn't link on Win32, Win64, or Android.  It works on linux and FreeBSD.  Here's the output on platforms where it doesn't work:

Win 7 x64 with dmd 2.064.2:
C:\dmd2>.\windows\bin\dmd.exe -m32 test.d
OPTLINK (R) for Win32  Release 8.00.13
Copyright (C) Digital Mars 1989-2010  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
test.obj(test)
 Error 42: Symbol Undefined _stderr
--- errorlevel 1

C:\dmd2>.\windows\bin\dmd.exe -m64 test.d
test.obj : error LNK2019: unresolved external symbol stderr referenced in functi
on main
test.exe : fatal error LNK1120: 1 unresolved externals
--- errorlevel 1120

Arch linux x86 compiling for Android x86:

test.o:test.d:function main: error: undefined reference to 'stderr'

The linker seems to find the symbol for stderr on platforms where it's defined extern in libc.  On platforms like Android, with the following stdio.h and stdio.d, not so much.

Android:
stdio.h:
__BEGIN_DECLS
extern FILE __sF[];
__END_DECLS
--snip--
#define stdin   (&__sF[0])
#define stdout  (&__sF[1])
#define stderr  (&__sF[2])
https://android.googlesource.com/platform/bionic/+/master/libc/include/stdio.h

My stdio.d:

else version( Android )
{
    enum
    {
        _IOFBF = 0,
        _IOLBF = 1,
        _IONBF = 2,
    }

    private extern shared FILE[3] __sF;

        shared stdin  = &__sF[0];
        shared stdout = &__sF[1];
        shared stderr = &__sF[2];
}

I followed the example of Solaris and Win32, but it appears those don't work either.  My guess is that OS X will work and Solaris won't, based on these similarities, but I don't have either accessible to test on.  If I call &__sF[2] directly from test.d, that does work on Android.

So the question is, when one has a #define macro like the above, how does one create the equivalent symbol in D?  It appears that the authors of druntime are unsure of how to do this also.
December 01, 2013
Alright, submitted my first pull request for Android support in druntime:

https://github.com/D-Programming-Language/druntime/pull/681

I'll push all further changes to druntime in my android branch:

https://github.com/joakim-noah/druntime/tree/android

Hopefully, I can get some subset of D working on Android/x86 over the next couple weeks. :)
December 02, 2013

On 01.12.2013 14:30, Joakim wrote:
> //test.d
> import core.stdc.stdio;
>
> extern (C) int main() { fputs("doing this for real?", stderr); return 0;}
>
> It doesn't link on Win32, Win64, or Android.  It works on linux and
> FreeBSD.  Here's the output on platforms where it doesn't work:

The reason this does not work on Win32/Win64 comes from declaring main as "extern(C)", which declares "main" for the C runtime. This prevents adding an implicite include directive to add the phobos library to the link. This happens only for D's main.

So, you should either drop the "extern(C)" or add phobos.lib to the command line.

If including the library is not an option, you'll have to repeat the respective declarations in your source. Just adding core.stdc.stdio to the command line might also work.
December 02, 2013
On Monday, 2 December 2013 at 08:25:39 UTC, Rainer Schuetze wrote:
>
>
> On 01.12.2013 14:30, Joakim wrote:
>> //test.d
>> import core.stdc.stdio;
>>
>> extern (C) int main() { fputs("doing this for real?", stderr); return 0;}
>>
>> It doesn't link on Win32, Win64, or Android.  It works on linux and
>> FreeBSD.  Here's the output on platforms where it doesn't work:
>
> The reason this does not work on Win32/Win64 comes from declaring main as "extern(C)", which declares "main" for the C runtime. This prevents adding an implicite include directive to add the phobos library to the link. This happens only for D's main.
I just tested this: you're right, removing the "extern (C)" linkage for main fixes the linking problem on Win32/Win64.  That makes sense that druntime/phobos wasn't added to the link, as the symbols _were_ added by the above stdio.d for Android.

Where is this "implicit include directive?"  It's confusing because "dmd -v" shows the exact same linker command being run whether that "extern (C)" is there before main or not.

> So, you should either drop the "extern(C)" or add phobos.lib to the command line.
Yes, both do fix the problem.

> If including the library is not an option, you'll have to repeat the respective declarations in your source. Just adding core.stdc.stdio to the command line might also work.
I was reusing the existing Makefiles as much as possible and archiving the ported core.stdc druntime object files for Android into a libphobos2.a, as that library name is hardcoded into dmd.  Perhaps that was a mistake, I'll look further into why it doesn't link.
December 02, 2013

On 02.12.2013 10:36, Joakim wrote:
> On Monday, 2 December 2013 at 08:25:39 UTC, Rainer Schuetze wrote:
>>
>>
>> On 01.12.2013 14:30, Joakim wrote:
>>> //test.d
>>> import core.stdc.stdio;
>>>
>>> extern (C) int main() { fputs("doing this for real?", stderr); return
>>> 0;}
>>>
>>> It doesn't link on Win32, Win64, or Android.  It works on linux and
>>> FreeBSD.  Here's the output on platforms where it doesn't work:
>>
>> The reason this does not work on Win32/Win64 comes from declaring main
>> as "extern(C)", which declares "main" for the C runtime. This prevents
>> adding an implicite include directive to add the phobos library to the
>> link. This happens only for D's main.
> I just tested this: you're right, removing the "extern (C)" linkage for
> main fixes the linking problem on Win32/Win64.  That makes sense that
> druntime/phobos wasn't added to the link, as the symbols _were_ added by
> the above stdio.d for Android.
>
> Where is this "implicit include directive?"  It's confusing because "dmd
> -v" shows the exact same linker command being run whether that "extern
> (C)" is there before main or not.

The compiler embeds it into the object file if code for "D main" is generated. The respective code is around line 742, glue.c.

>
>> So, you should either drop the "extern(C)" or add phobos.lib to the
>> command line.
> Yes, both do fix the problem.
>
>> If including the library is not an option, you'll have to repeat the
>> respective declarations in your source. Just adding core.stdc.stdio to
>> the command line might also work.
> I was reusing the existing Makefiles as much as possible and archiving
> the ported core.stdc druntime object files for Android into a
> libphobos2.a, as that library name is hardcoded into dmd. Perhaps that
> was a mistake, I'll look further into why it doesn't link.

IIRC it is not possible to embed a linker directive into an ELF object file, so it must always be specified on the command line. Maybe the linker is looking for libphobos2.a in the wrong directories?

You can change the name of the runtime library with -defaultlib.