October 15, 2012
Adam D. Ruppe:

> You could just version it:
>
> version(foo_main)
> void main() {}

That's not good enough.

What I as talking about is: when the D compilers know a module is
the main module, it defines a _standard_ version boolean flag,
named like "is_main_module" as true. And it gives a compiler
error if it can't find a main. Otherwise "is_main_module" is
false.

It's meant to be used as:


module modulea;
int foo() { return 0; }
static if (is_main_module) {
   unittest {}
   void main() { // demo code
     import std.stdio;
     writeln(foo());
   }
}



module moduleb;
import modulea;
int bar() { return 1; }
static if (is_main_module) {
   unittest {}
   void main() { // demo code
     import std.stdio;
     writeln(foo());
     writeln(bar());
   }
}


When you compile modulea, defines its is_main_module as true, it
runs its unittests (if you have used -unittest), and its main,
that is a demo for the A module.

If you compile the moduleb (with rdmd or something), it knows
moduleb has to contain the main, it defines is_main_module=true
in moduleb and defines is_main_module=false for modulea. So it
compiles the main of moduleb and ignores the main of modulea. So
it runs the demo code for moduleb only.

Using a non-standard user-defined version as you suggest misses
all this, and it's not good enough. Standardization and
automation is important here.

Bye,
bearophile
October 15, 2012
On 15 October 2012 08:23, Gerry Weaver <gerryw@compvia.com> wrote:
> On Monday, 15 October 2012 at 07:12:03 UTC, Iain Buclaw wrote:
>>
>> On 15 October 2012 04:10, Gerry Weaver <gerryw@compvia.com> wrote:
>>>
>>> Hello All,
>>>
>>> I have been looking at D off and on for several years. Initially I worked
>>> through a very painful experience to get D compiling on Linux. After that
>>> experience, I concluded that I should wait for it to become more mature.
>>> Since then, I do a very simple test. I install the latest package and try
>>> to
>>> build "Hello World". I figure that if "Hello World" builds successfully,
>>> I
>>> will continue further. I have just downloaded the latest .deb package and
>>> installed it on Ubuntu 12.04 32bit. Once again it fails this incredibly
>>> simple test. I've read many discussions about how/why, has/hasn't,
>>> will/won't D hit the mainstream in programming languages. I think this
>>> situation may offer at least one data point. I'm struggling to think of
>>> any
>>> other language (and I use several) that won't build code out of the box.
>>> D
>>> seems to have a lot of potential, but this needs to be fixed. I am not
>>> asking for help on this. I honestly don't care what the solution is. I
>>> just
>>> wanted the D developers to know why at least one developer is not using
>>> the
>>> language. I sincerely hope that the situation will improve. I'm looking
>>> forward to programming in D.
>>>
>>> Thanks for your time,
>>> -G
>>>
>>>
>>>
>>> Here is the code:
>>>
>>> import std.stdio;
>>>
>>>
>>> void main()
>>> {
>>>   writeln("Hello, world!");
>>> }
>>>
>>> Here is the command:
>>>
>>> dmd hello.d
>>>
>>> Here is the output:
>>>
>>> /usr/lib/i386-linux-gnu/libphobos2.a(dmain2_459_1a5.o): In function
>>> `_D2rt6dmain24mainUiPPaZi7runMainMFZv':
>>> src/rt/dmain2.d:(.text._D2rt6dmain24mainUiPPaZi7runMainMFZv+0x10):
>>> undefined
>>> reference to `_Dmain'
>>> /usr/lib/i386-linux-gnu/libphobos2.a(thread_18f_1b8.o): In function
>>> `_D4core6thread6Thread6__ctorMFZC4core6thread6Thread':
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFZC4core6thread6Thread+0x1d): undefined reference to `_tlsend'
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFZC4core6thread6Thread+0x24):
>>> undefined reference to `_tlsstart'
>>> /usr/lib/i386-linux-gnu/libphobos2.a(thread_19f_6e4.o): In function
>>> `thread_attachThis':
>>> src/core/thread.d:(.text.thread_attachThis+0xb7): undefined reference to
>>> `_tlsstart'
>>> src/core/thread.d:(.text.thread_attachThis+0xbc): undefined reference to
>>> `_tlsend'
>>> /usr/lib/i386-linux-gnu/libphobos2.a(thread_17d_1b8.o): In function
>>> `_D4core6thread6Thread6__ctorMFPFZvkZC4core6thread6Thread':
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvkZC4core6thread6Thread+0x1d): undefined reference to `_tlsend'
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvkZC4core6thread6Thread+0x27): undefined reference to `_tlsstart' /usr/lib/i386-linux-gnu/libphobos2.a(thread_17e_1b8.o): In function `_D4core6thread6Thread6__ctorMFDFZvkZC4core6thread6Thread':
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFDFZvkZC4core6thread6Thread+0x1d): undefined reference to `_tlsend'
>>>
>>> src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFDFZvkZC4core6thread6Thread+0x27): undefined reference to `_tlsstart' /usr/lib/i386-linux-gnu/libphobos2.a(deh2_43b_525.o): In function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh29FuncTable':
>>>
>>> src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh29FuncTable+0x4): undefined reference to `_deh_beg'
>>>
>>> src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh29FuncTable+0xc): undefined reference to `_deh_beg'
>>>
>>> src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh29FuncTable+0x13): undefined reference to `_deh_end'
>>>
>>> src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh29FuncTable+0x36):
>>> undefined reference to `_deh_end'
>>> /usr/lib/i386-linux-gnu/libphobos2.a(thread_17a_713.o): In function
>>> `thread_entryPoint':
>>> src/core/thread.d:(.text.thread_entryPoint+0x64): undefined reference to
>>> `_tlsend'
>>> src/core/thread.d:(.text.thread_entryPoint+0x6a): undefined reference to
>>> `_tlsstart'
>>> collect2: ld returned 1 exit status
>>> --- errorlevel 1
>>>
>>>
>>
>> Try and paste the output of the following:
>>
>> dmd -c hello.d
>> objdump -d hello.o
>>
>>
>> Regards
>
>
> Hi,
>
> Here you go.
>
> hello.o:     file format elf32-i386
>
>
> Disassembly of section .text:
>
> 00000000 <.text>:
>    0:   b8 10 00 00 00          mov    $0x10,%eax
>    5:   b9 00 00 00 00          mov    $0x0,%ecx
>    a:   8b 11                   mov    (%ecx),%edx
>    c:   89 10                   mov    %edx,(%eax)
>    e:   89 01                   mov    %eax,(%ecx)
>   10:   c3                      ret
>
>
> Thanks,
> -G
>


That looks to me as if hello.d is an empty file.


Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 15, 2012
On 10/14/2012 10:14 PM, Gerry Weaver wrote:
> I checked it out. There is only a dmd.conf. I've included it below.

Try the following:

locate dmd.conf
locate dmd
locate libphobos2.a
locate object.di

and see if there are any extras of these floating around.
October 15, 2012
On 10/14/2012 11:43 PM, Alex Rønne Petersen wrote:
> Yep, those errors are always a sign that a proper main function is missing. I
> have no idea why you would get it otherwise, though.

What happens is when the compiler sees main(), it triggers the compiler to emit a bunch of extra declarations into the object file. The missing symbols Gerry is seeing are just those declarations.
October 15, 2012
On Monday, 15 October 2012 at 13:11:29 UTC, bearophile wrote:
> Adam D. Ruppe:
>
>> You could just version it:
>>
>> version(foo_main)
>> void main() {}
>
> That's not good enough.
>
> What I as talking about is: when the D compilers know a module is
> the main module, it defines a _standard_ version boolean flag,
> named like "is_main_module" as true. And it gives a compiler
> error if it can't find a main. Otherwise "is_main_module" is
> false.
>
> It's meant to be used as:
>
>
> module modulea;
> int foo() { return 0; }
> static if (is_main_module) {
>    unittest {}
>    void main() { // demo code
>      import std.stdio;
>      writeln(foo());
>    }
> }
>
>
>
> module moduleb;
> import modulea;
> int bar() { return 1; }
> static if (is_main_module) {
>    unittest {}
>    void main() { // demo code
>      import std.stdio;
>      writeln(foo());
>      writeln(bar());
>    }
> }
>
>
> When you compile modulea, defines its is_main_module as true, it
> runs its unittests (if you have used -unittest), and its main,
> that is a demo for the A module.
>
> If you compile the moduleb (with rdmd or something), it knows
> moduleb has to contain the main, it defines is_main_module=true
> in moduleb and defines is_main_module=false for modulea. So it
> compiles the main of moduleb and ignores the main of modulea. So
> it runs the demo code for moduleb only.
>
> Using a non-standard user-defined version as you suggest misses
> all this, and it's not good enough. Standardization and
> automation is important here.
>
> Bye,
> bearophile

I'm sorry to say but that *is* a _horrible_ _hack_. It looks almost as awful as it does in python with the underscores.

Java has the correct DRY solution - each class can define a static main method but the compiler only uses the one specified by a compiler switch.
The above basically asks the programmer to endlessly repeat the same trivial implementation boilerplate that should be written just once _in_ the compiler.
October 15, 2012
On 10/15/12 7:24 AM, Paulo Pinto wrote:
> On Monday, 15 October 2012 at 11:20:26 UTC, bearophile wrote:
>> Jacob Carlborg:
>>
>>> How should DMD detect if you're building a (dynamic) library? Sure it
>>> can see that you're not using -lib or -shared but what about separate
>>> complication?
>>
>> What about the need to use a compiler switch if you are performing a
>> separate compilation?
>>
>> A related enhancement request that I'm asking for since years is: the
>> compiler could define a compile-time constant (like is_main_module or
>> something) as true if the module contains the main, and false
>> otherwise. This allows to have a main() in each module. This is handy
>> to have, it allows to compile&run modules both as normal modules to
>> import, or to compile and run them as stand alone programs, like when
>> you want a module to show a demo of its capabilities, or just run its
>> unittests.
>>
>> Bye,
>> bearophile
>
> Yes, this is a nice thing Java, .NET and Python have.

Wonder if a simple convention would suffice, e.g. every module that wanna defines a moduleMain(string[] args) and then you have one module main.d that has:

void main(string[] args) { import wuddever; moduleMain(args); }


Andrei


October 15, 2012
foobar:

> I'm sorry to say but that *is* a _horrible_ _hack_. It looks almost as awful as it does in python with the underscores.
>
> Java has the correct DRY solution - each class can define a static main method but the compiler only uses the one specified by a compiler switch.
> The above basically asks the programmer to endlessly repeat the same trivial implementation boilerplate that should be written just once _in_ the compiler.

What I have suggested is the simplest (requires less stuff to be implemented) way to solve the problem, adding just a single compile time constant. But I agree there are better ways to solve the same problem. I am asking for a specific way to solve this problem, but since some years I'd like some "good enough" way to solve it.

Bye,
bearophile
October 15, 2012
> I am asking for a specific way to solve this problem,

Sorry, I am not asking for a specific way to solve this problem, but...

Bye,
bearophile
October 15, 2012
On 10/15/2012 06:22 AM, Iain Buclaw wrote:
> On 15 October 2012 08:23, Gerry Weaver<gerryw@compvia.com>  wrote:

>> Disassembly of section .text:
>>
>> 00000000<.text>:
>>     0:   b8 10 00 00 00          mov    $0x10,%eax
>>     5:   b9 00 00 00 00          mov    $0x0,%ecx
>>     a:   8b 11                   mov    (%ecx),%edx
>>     c:   89 10                   mov    %edx,(%eax)
>>     e:   89 01                   mov    %eax,(%ecx)
>>    10:   c3                      ret
>>
>>
>> Thanks,
>> -G
>>
>
>
> That looks to me as if hello.d is an empty file.

That is the most plausible reason so far: The OP has an empty file in the current directory but the hello.d that is being edited in Emacs is elsewhere. :)

Ali

October 15, 2012
On Monday, 15 October 2012 at 15:22:38 UTC, Andrei Alexandrescu wrote:
<snip>
>>
>> Yes, this is a nice thing Java, .NET and Python have.
>
> Wonder if a simple convention would suffice, e.g. every module that wanna defines a moduleMain(string[] args) and then you have one module main.d that has:
>
> void main(string[] args) { import wuddever; moduleMain(args); }
>
>
> Andrei

Great idea! But why add another (redundant) level of indirection?
It should go in the C main in druntime together with a mechanism to call the correct D main, by e.g. reading the module name from the command line.