www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Strange behaviour of rdmd vs. dmd concerning main function

reply berni <berni example.com> writes:
I've got two source files in two directories:

Common/common.d

module common;

import std.stdio;

int main(string[] args)
{
    Foo foo = cast(Foo)Object.factory("special.Bar");

    foo.do_something();

    return 0;
}

abstract class Foo {
    abstract void do_something();
}
Special/special.d
module special;

import std.stdio;
import common;

class Bar : Foo {
    override void do_something()
    {
        writeln("works");
    }
}
Now I try to run it with rdmd and dmd and get quite different results:
$> rdmd -ICommon Special/special.d
works
$> dmd -ICommon Special/special.d
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o: In function
`_start':
(.text+0x20): undefined reference to `main'
special.o:(.data.rel.ro+0x18): undefined reference to 
`_D6common12__ModuleInfoZ'
special.o:(.data._D7special3Bar7__ClassZ+0x50): undefined 
reference to `_D6common3Foo7__ClassZ'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
I encountered this, when I was curious if I can move the main function to a diffent module, because it will be the same in several modules anyway. When testing with rdmd, everything worked. Later, I found out, that with dmd it doesn't. (And with gdc and ldc2 it doesn't work too.) For me, this looks like a bug in either rdmd or dmd. But maybe there is something about it that I do not understand.
Feb 09 2017
parent reply via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Thu, Feb 09, 2017 at 03:39:18PM +0000, berni via Digitalmars-d-learn wrote:
 Now I try to run it with rdmd and dmd and get quite different results:
dmd only compiles in the files you actually pass to it. rdmd will try to find the required files automatically. Since you didn't pass the file with the function to dmd, it knows it exists, but leaves it out of the final link (it assumes it might come from a library or something). That's why you see the error. rdmd exists because it handles it more automatically.
Feb 09 2017
parent reply berni <berni example.com> writes:
 dmd only compiles in the files you actually pass to it. rdmd 
 will try to find the required files automatically.

 Since you didn't pass the file with the function to dmd, it 
 knows it exists, but leaves it out of the final link (it 
 assumes it might come from a library or something). That's why 
 you see the error.
Ah ok, I understand. So calling with "dmd Special/special.d Common/common.d" works. But when I compile common.d to common.o (with dmd -c common.d) and remove common.d after that is there still a possibility to link? The obvious doesn't work:
$> dmd Special/special.d Common/common.o Special/special.d(4): 
Error: module common is in file 'common.d' which cannot be read
import path[0] = /usr/include/dmd/phobos
import path[1] = /usr/include/dmd/druntime/import
Feb 09 2017
next sibling parent reply Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 9.2.2017 v 17:20 berni via Digitalmars-d-learn napsal(a):

 dmd only compiles in the files you actually pass to it. rdmd will try 
 to find the required files automatically.

 Since you didn't pass the file with the function to dmd, it knows it 
 exists, but leaves it out of the final link (it assumes it might come 
 from a library or something). That's why you see the error.
Ah ok, I understand. So calling with "dmd Special/special.d Common/common.d" works. But when I compile common.d to common.o (with dmd -c common.d) and remove common.d after that is there still a possibility to link? The obvious doesn't work:
 $> dmd Special/special.d Common/common.o Special/special.d(4): Error: 
 module common is in file 'common.d' which cannot be read
 import path[0] = /usr/include/dmd/phobos
 import path[1] = /usr/include/dmd/druntime/import
Thats ok too, you still need to add -ICommon dmd -ICommon Special/special.d Common/common.o
Feb 09 2017
parent reply berni <berni example.com> writes:
On Thursday, 9 February 2017 at 19:10:55 UTC, Daniel Kozak wrote:
 Dne 9.2.2017 v 17:20 berni via Digitalmars-d-learn napsal(a):

 [...]
Ah ok, I understand. So calling with "dmd Special/special.d Common/common.d" works. But when I compile common.d to common.o (with dmd -c common.d) and remove common.d after that is there still a possibility to link? The obvious doesn't work:
 [...]
Thats ok too, you still need to add -ICommon dmd -ICommon Special/special.d Common/common.o
Doesn't work here:
$> dmd -ICommon Special/special.d Common/common.o
Special/special.d(4): Error: module common is in file 'common.d' 
which cannot be read
import path[0] = Common
import path[1] = /usr/include/dmd/phobos
import path[2] = /usr/include/dmd/druntime/import
Feb 09 2017
parent Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Dne 9.2.2017 v 21:10 berni via Digitalmars-d-learn napsal(a):

 On Thursday, 9 February 2017 at 19:10:55 UTC, Daniel Kozak wrote:
 Dne 9.2.2017 v 17:20 berni via Digitalmars-d-learn napsal(a):

 [...]
Ah ok, I understand. So calling with "dmd Special/special.d Common/common.d" works. But when I compile common.d to common.o (with dmd -c common.d) and remove common.d after that is there still a possibility to link? The obvious doesn't work:
 [...]
Thats ok too, you still need to add -ICommon dmd -ICommon Special/special.d Common/common.o
Doesn't work here:
 $> dmd -ICommon Special/special.d Common/common.o
 Special/special.d(4): Error: module common is in file 'common.d' 
 which cannot be read
 import path[0] = Common
 import path[1] = /usr/include/dmd/phobos
 import path[2] = /usr/include/dmd/druntime/import
Which version of dmd you have? It should work, you probably do something wrong, I have use your example files so do you change them somehow?
Feb 09 2017
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 9 February 2017 at 16:20:29 UTC, berni wrote:
 dmd only compiles in the files you actually pass to it. rdmd 
 will try to find the required files automatically.

 Since you didn't pass the file with the function to dmd, it 
 knows it exists, but leaves it out of the final link (it 
 assumes it might come from a library or something). That's why 
 you see the error.
Ah ok, I understand. So calling with "dmd Special/special.d Common/common.d" works. But when I compile common.d to common.o (with dmd -c common.d) and remove common.d after that is there still a possibility to link? The obvious doesn't work:
$> dmd Special/special.d Common/common.o Special/special.d(4): 
Error: module common is in file 'common.d' which cannot be read
import path[0] = /usr/include/dmd/phobos
import path[1] = /usr/include/dmd/druntime/import
This is not a linker error. It's a compiler error. You need common.d for the import, so the compiler can know which symbols are available. For any modules you import, you need either the original source file (.d) or a D interface (header) file (.di) which contains the type & function declarations and any template implementations you need.
Feb 09 2017
parent reply berni <berni example.com> writes:
$> dmd Special/special.d Common/common.o Special/special.d(4): 
Error: module common is in file 'common.d' which cannot be read
import path[0] = /usr/include/dmd/phobos
import path[1] = /usr/include/dmd/druntime/import
This is not a linker error. It's a compiler error. You need common.d for the import, so the compiler can know which symbols are available. For any modules you import, you need either the original source file (.d) or a D interface (header) file (.di) which contains the type & function declarations and any template implementations you need.
That worked. With "dmd -c -Hd=Common Common/common.d" I created a common.di file then I removed the common.d and could compile with "dmd -ICommon Special/special.d Common/common.o". With this, common.d does not need to be recompiled a lot of times if there are several special.d-files. Thank you!
Feb 10 2017
parent reply berni <berni example.com> writes:
Something similar happend now, but this time it works with dmd 
and rdmd produces the error:

The command that works is

dmd a.d b.o

where b.o is a precompiled c file, similar to 
https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.c

When using rdmd it doesn't work anymore. When I make rdmd 
--chatty, I can find the reason: b.o is ommited in the call of 
dmd. How can I make rdmd pass this parameter to dmd too?
Feb 17 2017
parent ag0aep6g <anonymous example.com> writes:
On 02/17/2017 07:41 PM, berni wrote:
 The command that works is

 dmd a.d b.o

 where b.o is a precompiled c file, similar to
 https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.c

 When using rdmd it doesn't work anymore. When I make rdmd --chatty, I
 can find the reason: b.o is ommited in the call of dmd. How can I make
 rdmd pass this parameter to dmd too?
You have to pass the .o file before the .d file. rdmd interprets everything that comes after the .d file as arguments to the generated program.
Feb 17 2017