July 10, 2013
On 10 July 2013 12:24, Joseph Rushton Wakeling <joseph.wakeling@webdrake.net> wrote:
> On 07/10/2013 12:56 PM, Iain Buclaw wrote:
>> You think too hard about things that simply don't matter.
>
> ... scratches head furiously and thinks about how to respond to this ...
>
> :-P

http://25.media.tumblr.com/tumblr_lw997zALj91r1tloio1_500.gif


--
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
July 10, 2013
On Wednesday, 10 July 2013 at 10:24:17 UTC, Joseph Rushton Wakeling wrote:
> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
>> Comments / flames / pull requests welcome. ;-)
>
>     string findGDC(string argv0)
>     {
>         // FIXME: this does not work 100% of the time.
>         auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
>         auto targetPrefix = c[1];
>         auto gdcDir = absolutePath(dirName(argv0));
>         return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
>     }

This is just bad:

main(string[] args) calls init(args) that calls findGDC(args[0]) that gives auto gdcDir = absolutePath(dirName(argv0));

Which is not good:

findGDC: argv0=gdmd
findGDC: dirName(argv0)=.
findGDC: gdcDir=/home/user/github/gdmd/.

That is: it will look for gdc in the current folder, which is not even the base folder of gdmd (eg. /usr/bin), but the working directory.

In other words, it looks for gdc in the current working folder.

Then it complains:

Not an executable file: /home/user/github/gdmd/gdc

which is understandable.

I think it should simply look on the PATH.
July 10, 2013
On Wednesday, 10 July 2013 at 12:03:06 UTC, eles wrote:
> On Wednesday, 10 July 2013 at 10:24:17 UTC, Joseph Rushton Wakeling wrote:
>> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
>>> Comments / flames / pull requests welcome. ;-)
>>
>>    string findGDC(string argv0)
>>    {
>>        // FIXME: this does not work 100% of the time.
>>        auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
>>        auto targetPrefix = c[1];
>>        auto gdcDir = absolutePath(dirName(argv0));
>>        return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
>>    }

Quick and unportable (Linux-only) drop-in replacement:

string findGDC(string argv0)
{
    // FIXME: this does not work 100% of the time.
    auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
    auto targetPrefix = c[1];
	
	auto which = executeShell("which gdc");
	if (which.status == 0){
		writeln("Failed to execute which.");
	}
	else {
		writefln("which returned %s", which.output);
	}
	
	auto gdcDir = absolutePath(dirName(which.output));
	writefln("new findGDC: gdcDir=%s", gdcDir);
    return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
}
July 10, 2013
On Wednesday, 10 July 2013 at 12:14:39 UTC, eles wrote:
> On Wednesday, 10 July 2013 at 12:03:06 UTC, eles wrote:
>> On Wednesday, 10 July 2013 at 10:24:17 UTC, Joseph Rushton Wakeling wrote:
>>> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
>>>> Comments / flames / pull requests welcome. ;-)
>>>
>>>   string findGDC(string argv0)
>>>   {
>>>       // FIXME: this does not work 100% of the time.
>>>       auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
>>>       auto targetPrefix = c[1];
>>>       auto gdcDir = absolutePath(dirName(argv0));
>>>       return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
>>>   }

Actually, I think this is better (diff wrt the Teoh's version):

diff --git a/gdmd.d b/gdmd.d
index 6607ce2..4c7e3eb 100644
--- a/gdmd.d
+++ b/gdmd.d
@@ -262,7 +262,14 @@ Config init(string[] args)
 {
     auto cfg = new Config();
     cfg.scriptPath = findScriptPath(args[0]);
-    cfg.gdc = findGDC(args[0]);
+       auto which = executeShell("which gdc");
+       if (which.status == 0){
+               writeln("Failed to execute which.");
+       }
+       else {
+               writefln("which returned %s", which.output);
+       }
+    cfg.gdc = findGDC(which.output);
     cfg.linker = cfg.gdc;

     readDmdConf(cfg);

July 10, 2013
On Wednesday, 10 July 2013 at 12:20:14 UTC, eles wrote:
> On Wednesday, 10 July 2013 at 12:14:39 UTC, eles wrote:
>> On Wednesday, 10 July 2013 at 12:03:06 UTC, eles wrote:
>>> On Wednesday, 10 July 2013 at 10:24:17 UTC, Joseph Rushton Wakeling wrote:
>>>> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
>>>>> Comments / flames / pull requests welcome. ;-)
>>>>
>>>>  string findGDC(string argv0)
>>>>  {
>>>>      // FIXME: this does not work 100% of the time.
>>>>      auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
>>>>      auto targetPrefix = c[1];
>>>>      auto gdcDir = absolutePath(dirName(argv0));
>>>>      return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
>>>>  }
>
> Actually, I think this is better

or worse. Since it asks findGDC() to unwind, then wind again the path towards gdc.

Isn't resonable to implement a Linux-like "which" function? Could even find its place in phobos.
July 10, 2013
On 10 July 2013 13:14, eles <eles@eles.com> wrote:
> On Wednesday, 10 July 2013 at 12:03:06 UTC, eles wrote:
>>
>> On Wednesday, 10 July 2013 at 10:24:17 UTC, Joseph Rushton Wakeling wrote:
>>>
>>> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
>>>>
>>>> Comments / flames / pull requests welcome. ;-)
>>>
>>>
>>>    string findGDC(string argv0)
>>>    {
>>>        // FIXME: this does not work 100% of the time.
>>>        auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
>>>        auto targetPrefix = c[1];
>>>        auto gdcDir = absolutePath(dirName(argv0));
>>>        return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
>>>    }
>
>
> Quick and unportable (Linux-only) drop-in replacement:
>

Christ on a bike.  What's wrong with:

import std.file;
import std.process : environment;

auto binpaths = environment.get("PATH");

foreach (path; binpaths.split(<delimiter>)
{
    auto exe = path ~ <dirsep> ~ "gdc";
    if (exists (exe)) {
      // found
    }
}


--
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
July 10, 2013
On Wednesday, 10 July 2013 at 12:58:41 UTC, Iain Buclaw wrote:
> On 10 July 2013 13:14, eles <eles@eles.com> wrote:
>> On Wednesday, 10 July 2013 at 12:03:06 UTC, eles wrote:
>> Quick and unportable (Linux-only) drop-in replacement:
>>
>
> Christ on a bike.  What's wrong with:
>
> import std.file;
> import std.process : environment;
>
> auto binpaths = environment.get("PATH");
>
> foreach (path; binpaths.split(<delimiter>)
> {
>     auto exe = path ~ <dirsep> ~ "gdc";
>     if (exists (exe)) {
>       // found
>     }
> }

Almost nothing (just a bracket). So, to make Teoh's life easier:

diff --git a/gdmd.d b/gdmd.d
index 6607ce2..12c610f 100644
--- a/gdmd.d
+++ b/gdmd.d
@@ -141,13 +141,19 @@ string findScriptPath(string argv0)
 /**
  * Finds GDC.
  */
-string findGDC(string argv0)
+string findGDC()
 {
-    // FIXME: this does not work 100% of the time.
-    auto c = match(baseName(argv0), `^(.*-)?g?dmd(-.*)?$`).captures;
-    auto targetPrefix = c[1];
-    auto gdcDir = absolutePath(dirName(argv0));
-    return buildNormalizedPath(gdcDir, targetPrefix ~ "gdc" ~ c[2]);
+       auto binpaths = environment.get("PATH");
+
+       foreach (path; binpaths.split(pathSeparator))
+       {
+          auto exe = path ~ dirSeparator ~ "gdc";
+          if (exists (exe)) {
+            return exe;
+          }
+       }
+
+       return "";
 }

 /**
@@ -262,7 +268,7 @@ Config init(string[] args)
 {
     auto cfg = new Config();
     cfg.scriptPath = findScriptPath(args[0]);
-    cfg.gdc = findGDC(args[0]);
+    cfg.gdc = findGDC();
     cfg.linker = cfg.gdc;

     readDmdConf(cfg);
July 10, 2013
On Wed, Jul 10, 2013 at 10:03:40AM +0200, Joseph Rushton Wakeling wrote:
> On 07/10/2013 02:07 AM, H. S. Teoh wrote:
> > I forked GDMD on github and took a first stab at D-ifying it:
> > 
> > 	https://github.com/quickfur/GDMD/tree/dport
> 
> Nice -- I'll try and have a play with that later :-)
> 
> First thing that strikes me -- and I know you're taking this from the original script -- what's with the references to dmd.conf?  GDC has no dmd.conf that I can recall (don't know whether it used to once upon a time), so this part of the script may even be dangerous if it winds up trying to find a config file that exists for dmd but not gdc/gdmd.

True. I suppose the idea was to make gdmd a possible drop-in replacement for dmd, so it would behave the same way as dmd would from the user's POV. But this may be dangerous if you have both dmd and gdc installed, and gdmd picks up the wrong settings intended only for dmd.


> I'd have thought this could be deleted without problem.  If there _is_ a conf script that needs using, it should be renamed to avoid potential clashes with DMD proper.

OK. I'll make the name an enum that can be changed later. At least, it'll be better than hardcoding the filename. ;-)


> > The new code is in gdmd.d -- I haven't updated the Makefile to build it yet, so you'll have to compile it by hand.  It can do very simple compiles now (list of .d files -> executable), including compile itself.  :) It can read dmd.conf and setup environment variables accordingly, though I haven't actually tested whether it's really doing what I think it's doing.  (Anybody up for writing unittests? ;-))
> 
> I think that unittests can focus first on checking that gdmd input translates into correct gdc output (as in, what you get right now running gdmd --someoptions -vdmd).  That is, we can check each of the gdmd options singly and ensure they translate to correct gdc call strings.
> 
> I'm not sure to what extent we'd need to test combinations of gdmd flags as opposed to single flags.  There's also the whole bogeyman of contradictory flags (e.g. one turns on the optimizations, one turns them off...).

The problem I ran into when I thought about unittests was, the unittest code basically has to do almost the same thing as what the code does anyway, so it's not really *testing* the code per se, but testing your ability to write the same code twice. I suppose we could test the more tricky spots with explicit samples, though, like the parts parsed with regexes.


T

-- 
The peace of mind---from knowing that viruses which exploit Microsoft system vulnerabilities cannot touch Linux---is priceless. -- Frustrated system administrator.
July 11, 2013
On Tue, Jul 09, 2013 at 05:07:59PM -0700, H. S. Teoh wrote: [...]
> I forked GDMD on github and took a first stab at D-ifying it:
> 
> 	https://github.com/quickfur/GDMD/tree/dport
[...]

Update:
- Fixed the path issues raised earlier (thanks for all the feedback!)

- I've added a whole bunch more code now, and a good number of dmd
  options are now understood. Most of the common ones are now supported,
  like -c, -inline, -O, and a few others. There's still a lot left to
  do, though. It never truly dawned on me before just how many options
  dmd has!  (Fortunately it's nowhere near the sheer number in gcc/gdc.
  ;-))

- Unittests were added!! Now I can feel less shameful. :-P

- Now gdmd can handle -of, -od, and -op. However, dmd appears to be
  extremely quirky in this area (esp. when these options are used
  together). Apparently, if the argument to -of contains '/', it
  implicitly sets -od as well. Gdmd still doesn't quite match dmd in
  this area.  One particularly problematic case is:

  Given this directory structure:
	./src
	./src/test.d

  Running dmd -ofbin/prog produces:
  	./bin
	./bin/prog
	./prog.o	<-- problem

  The trouble with this case is that currently gdmd always compiles each
  source file separately (following the behaviour of the old Perl
  script), so we can't just rename the default test.o to prog.o. Also,
  IME, running gdc with too many .d files at once can sometimes cause
  memory problems, so doing it one at a time seems preferable.

- The makefile has been updated to build gdmd from gdmd.d instead of the
  Perl script. If you build with make DFLAGS=-fdebug, you'll get some
  verbose output that may help track down problems when gdmd
  misbehgaves=-fdebug, you'll get some verbose output that may help
  track down problems when gdmd misbehaves.

For the rest of the details, take a look at the git log. :) Gotta run now.


T

-- 
A linguistics professor was lecturing to his class one day.
"In English," he said, "A double negative forms a positive. In some
languages, though, such as Russian, a double negative is still a
negative. However, there is no language wherein a double positive can
form a negative."
A voice from the back of the room piped up, "Yeah, yeah."
July 11, 2013
On Jul 11, 2013 1:28 AM, "H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote:
>
> On Tue, Jul 09, 2013 at 05:07:59PM -0700, H. S. Teoh wrote: [...]
> > I forked GDMD on github and took a first stab at D-ifying it:
> >
> >       https://github.com/quickfur/GDMD/tree/dport
> [...]
>
> Update:
> - Fixed the path issues raised earlier (thanks for all the feedback!)
>
> - I've added a whole bunch more code now, and a good number of dmd
>   options are now understood. Most of the common ones are now supported,
>   like -c, -inline, -O, and a few others. There's still a lot left to
>   do, though. It never truly dawned on me before just how many options
>   dmd has!  (Fortunately it's nowhere near the sheer number in gcc/gdc.
>   ;-))
>
> - Unittests were added!! Now I can feel less shameful. :-P
>
> - Now gdmd can handle -of, -od, and -op. However, dmd appears to be
>   extremely quirky in this area (esp. when these options are used
>   together). Apparently, if the argument to -of contains '/', it
>   implicitly sets -od as well. Gdmd still doesn't quite match dmd in
>   this area.  One particularly problematic case is:
>
>   Given this directory structure:
>         ./src
>         ./src/test.d
>
>   Running dmd -ofbin/prog produces:
>         ./bin
>         ./bin/prog
>         ./prog.o        <-- problem
>
>   The trouble with this case is that currently gdmd always compiles each
>   source file separately (following the behaviour of the old Perl

Are you sure on that?  :-)

My memory might be bad in this respect, but I seem to recall the script explicitly set the output program / object file name. (See below for why that matters ).

>   script), so we can't just rename the default test.o to prog.o. Also,
>   IME, running gdc with too many .d files at once can sometimes cause
>   memory problems, so doing it one at a time seems preferable.
>

Running dmd with too many .d files causes the same memory problems, but they tend to be short lived due to the speed of the compilation.

The difference between single and multiple file compilation is very subtle in gdc since the switch to LTO.

gdc foo.d bar.d.   # compiled separately.
gdc foo.d bar.d -o exe   # compiled together.

People from a dmd background I found expected the latter, and separate compilation also comes with its own quirks that don't occur during single compilation of all sources (the most common suggested work around for this being -femit-templates, though should give the switch -fonly some lovin' someday).

Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';