April 17, 2018
On Friday, 13 April 2018 at 03:56:24 UTC, Joakim wrote:
> On Wednesday, 11 April 2018 at 00:39:23 UTC, Mike Franklin wrote:
>> How does clang know how to generate its linker command?
>
> I don't think it does, it's probably hard-coded based on the target, though you can usually override various elements with flags. Since every target has its own selection of flags and object files it needs, we delegate linking to the C (cross-)compiler for that target.
>
> You can always choose your own linker for ldc with the -linker= flag and do everything manually if you want though.
>
>> Whatever it is, can ldc be made do the same?
>
> Yes, but it would be an impossible task to do it for any non-trivial set of platforms. It's _much_ easier to free-ride off the C compiler which has already been configured for the target.

Btw, you may be interested in this thread about using the llvm linker, lld, which delves into a lot of the issues involved with not delegating to the C compiler:

https://github.com/ldc-developers/ldc/issues/2028
April 17, 2018
On Tuesday, 17 April 2018 at 06:53:59 UTC, Joakim wrote:

> Btw, you may be interested in this thread about using the llvm linker, lld, which delves into a lot of the issues involved with not delegating to the C compiler:
>
> https://github.com/ldc-developers/ldc/issues/2028

Thanks, it was an interesting read.

IMO, however, all of this dependency and C (C runtime, C standard library, C compiler, etc...) is all superficial.  With a little more due diligence in the compiler and runtime implementations, none of it would be necessary.

I illustrate with the following example. It is a gross oversimplification but demonstrates that D doesn't need C...any of it.

---object.d
module object;

alias immutable(char)[] string;

private long __d_sys_write(long arg1, in void* arg2, long arg3)
{
    long result;

    asm
    {
        mov RAX, 1;
        mov RDI, arg1;
        mov RSI, arg2;
        mov RDX, arg3;
        syscall;
    }

    return result;
}

void write(string text)
{
    __d_sys_write(2, text.ptr, text.length);
}

private void __d_sys_exit(long arg1)
{
    asm
    {
        mov RAX, 60;
        mov RDI, arg1;
        syscall;
    }
}

extern void main();
private extern(C) void _start()
{
    main();
    __d_sys_exit(0);
}

---main.d
module main;

void main()
{
    write("Hello, World\n");
}

$dmd -c -lib -conf= object.d main.d -of=main.o
$ld main.o -o main
$size main
   text    data     bss     dec     hex filename
    176       0       0     176      b0 main
$main
Hello, World

I admit that without leveraging C (actually gcc, even llvm still needs the crt files from gcc) D would be assuming more work, but I think doing away with the C compiler and going directly to the linker is a step in the right direction.

Mike
April 18, 2018
On 2018-04-17 10:55, Mike Franklin wrote:

> IMO, however, all of this dependency and C (C runtime, C standard library, C compiler, etc...) is all superficial.  With a little more due diligence in the compiler and runtime implementations, none of it would be necessary.

I agree. That's one case where Go shines. It makes cross-compiling so much simpler.

-- 
/Jacob Carlborg
April 18, 2018
On Wednesday, 18 April 2018 at 19:08:50 UTC, Jacob Carlborg wrote:
> On 2018-04-17 10:55, Mike Franklin wrote:
>
>> IMO, however, all of this dependency and C (C runtime, C standard library, C compiler, etc...) is all superficial.  With a little more due diligence in the compiler and runtime implementations, none of it would be necessary.
>
> I agree. That's one case where Go shines. It makes cross-compiling so much simpler.

I don't see a huge problem for the compiler (except for quite a bunch of LLVM 'intrinsics' boiling down to a C function call, so LLVM expects some core C libs to be linked in as well - so these C symbols would need to be provided by a D lib).

Basing druntime on the C runtime layer, abstracting away many OS differences, makes things considerably simpler though; with the current manpower, I see no way to get rid of it and re-implement everything in D, while still supporting all platforms (and new platforms to come with as little hassle as possible). OTOH, libunwind (or for MSVC, the Visual C++ EH personality function used by LDC), libpthread, the math functions (which I'd really like to see all in pure D), I/O, memory management...

Considering that we'll be stuck with core.stdc anyway, getting rid of the C dependencies won't be feasible for a very long time IMO. A cross-compiler with integrated cross-linking ability (and a tool to cross-compile druntime and Phobos), shipping with ready-made C libs and a preconfigured config file in a Docker image, working just out of the box should be a great experience for the user (and the Docker image generation easily automatable for us devs). I've never used Go, so how can that experience be further improved?

April 18, 2018
On Wednesday, 18 April 2018 at 21:07:01 UTC, kinke wrote:
> A cross-compiler with integrated cross-linking ability (and a tool to cross-compile druntime and Phobos), shipping with ready-made C libs and a preconfigured config file in a Docker image, working just out of the box should be a great experience for the user (and the Docker image generation easily automatable for us devs).

It'd probably be quite cool to merge all prebuilt packages into a single universal Docker image (augmented by each platform's C libs & object files and the ldc2.conf config file extended by a section for each target triple). That would currently allow to freely cross-compile to 32/64-bit Windows/Linux/macOS and 32-bit ARM, simply depending on the used `-mtriple=...`. Legal aspects would need to be clarified first though; just saying that something like this wouldn't actually be that hard to do & automate.
April 19, 2018
On 2018-04-18 23:07, kinke wrote:

> I don't see a huge problem for the compiler (except for quite a bunch of LLVM 'intrinsics' boiling down to a C function call, so LLVM expects some core C libs to be linked in as well - so these C symbols would need to be provided by a D lib).
> 
> Basing druntime on the C runtime layer, abstracting away many OS differences, makes things considerably simpler though; with the current manpower, I see no way to get rid of it and re-implement everything in D, while still supporting all platforms (and new platforms to come with as little hassle as possible). OTOH, libunwind (or for MSVC, the Visual C++ EH personality function used by LDC), libpthread, the math functions (which I'd really like to see all in pure D), I/O, memory management...

Originally Tango, which druntime is based, only used syscalls and (as far as I know) a C main function and everything necessary for that. But druntime has evolved quite a lot since then with new features and more platforms.

> I've never used Go, so how can that experience be further improved?

The standard Go compiler is a cross-compiler. They use a custom linker which is a cross-linker as well. In Go you cannot directly link to a C function in the same way as you can in D. Go also requires (unless you want to mess with the whole reason to use Go) that every call is non-blocking. That means they need to reimplement most things and cannot rely on the C standard library. Therefore they don't and instead only using syscalls as the most basic layer.

Cross-compiling using Go is as simple as:

GOOS=linux GOARCH=arm go build main.go

Since the compiler and linker are cross-tools and they're not relaying on any platform SDK it just works if you have the standard Go package. No issues with trying to find a cross-linker, no issues of the SDK cannot be redistributed for macOS or Windows. It will even generate statically linked binaries on macOS which the C standard library doesn't even support.

-- 
/Jacob Carlborg
1 2
Next ›   Last »