Prototype buildsystem "Drake"

Nick Sabalausky a at a.a
Wed Jul 13 14:41:03 PDT 2011


"Jacob Carlborg" <doob at me.com> wrote in message
news:ivke5k$2m78$1 at digitalmars.com...
>
> First I have to say that I know you are doing this because you want to use 
> D as the language for the build scripts. The reason I did choose Ruby 
> because I think D will be too verbose and when I'm looking at drakefile.d 
> I do think it's too verbose.

Yea, D is likely to be a little more verbose than what could be done in Ruby 
(or Python). Personally, I think that's well worth it, though. I don't know 
how many others would agree or not.


> But instead of starting a debate between Ruby and D I'm going to give you 
> a few suggestions and comments instead.
>
> The minimal drakefile doesn't look that minimal.

I think I may be able to make the "immutable modes = [];" optional by 
checking for it with some compile-time reflecion.

The other parts I'll address further below...


> This is the idea I have for a minimal build script file:
>
> target("main.d"); // builds "main.d" as an executable
>
> Or:
>
> target("foobar"); // builds the directory "foobar" as a library
>
> DSSS did this very good.
>

I've never been very comfortable with build systems magically understanding 
and inferring all those details about a language and filetypes. It just 
feels too "magic", it's much more difficult to expand to new 
languages/tools, and every time I use a system like that I feel completely 
lost every time I need to include even just one custom buildstep.

However, Drake's design is expandable. Add-on modules can be created that 
define new target types, so you could do:

    module drake_dlang;
    class DLang : Target (or File)
    {
        //...etc
    }

    target!DLang("main.d");

And that would essentially wrap a File target, adding in any D-specific 
things such as "The target is 'main.exe'". And if you really wanted you 
could take it one more step and do:

    void targetD(string source)
    {
        target!DLang(source);
    }

    targetD("main.d");


Good add-ons could even be folded into the standard Drake.


> Now looking in the drakefile.d. You have targets and tasks all over the 
> place, almost every target has "Task" as a template parameter. Why is this 
> necessary? Have one function for targets and one for tasks. Example from 
> the drakefile.d:
>
>         target!Task("upload", "all",
>                 (Target t)
>                 {
>                         system("ftp ...");
>                 }
>         );
>
> Seems this could look like this:
>
> task("upload", "all", {
>     system("ftp...");
> }); // if D just could get a better looking delegate syntax
>

Some Drake terminology first: Every "node" in the dependency tree is a 
"Target". There are three pre-defined types of targets: "Task", "File" and 
"Dir". Other new target types can also be defined. So the template param is 
due to that.

However, I suppose it may be a good idea for every target type to come with 
a matching shortcut:

    alias target!Task task;
    alias target!File file;
    alias target!Dir  dir;

Then your "task("upload", ...);" example should work.

I agree that D's delegate syntax could be better. I think something like 
your example would be possible, but I ran into what seemed like some type 
inference limitations with all the overloading and templates, etc.


> "getDCompiler" seems unnecessary, both ldc and gdc have a dmd compatible 
> wrapper, ldmd and gdmd. These wrappers takes the same flags as dmd and 
> translate them to the correct "native" flags.
>

That's great, I didn't know that. But, you still have to say "ldmd" or 
"gdmd" instead of "dmd". And since the idea of "getDCompiler" is to allow 
the user to select which compiler to use (if the drakefile's author wants to 
support that), something roughly like "getDCompiler" may still be needed, 
albeit in a greatly simplified form.

In any case, it was just an example of using the "modes" feature.


> The "drakfile" function seems unnecessary. I would use a string import (or 
> what it's called), importing the whole build script into a method in a 
> class. All code in the "drakefile" function would instead be at top level.
>

I'm not entirely opposed to that idea, but here are the (perhaps minor?) 
reasons I did it this way:

- Using "import" inside functions is brand-new and likely still buggy. And 
unless I'm mistaken, I think there's other problems that still exist with 
using the same code inside a function as outside (such as some 
order-of-declaration limitations, IIRC). I wanted to get moving on something 
that would work reliably right away without being too sensitive to bleeding 
edge-cases. I figured if all that gets sorted out later on, then maybe a 
Drake v2 could go that route.

- I wasn't sure if a D file that isn't strictly a proper D file would be too 
weird, too confusing, too magical, or would confuse the fuck out of advanced 
IDE's.

If those are really just totally bullshit reasons, then I'm certainly open 
to the idea of doing it as you suggest.


> Most of the functions called in the build script should be instance 
> methods, this will allow to use threading, possible invoke multiple 
> targets/tasks simultaneously and running several build scripts 
> simultaneously.
>

My understanding is that with thread-local being the default, they *don't* 
need to be instance methods to be thread-safe.

Also, dependency-checking and task-invocation (once they're implemented) 
won't occur at all until *after* the drakefile() function completes. The 
target!...(...) function merely defines the targets, adding them to an 
internal list - nothing more. So I'm not sure that's not really a 
thread-appropriate matter.

Not really sure what you mean about running several build scripts 
simultaneously. The buildscript gets compiled into an exe, so the 
buildscripts all run in separate processes anyway.


> I see installation related code in the build script. I think a package 
> manager should be responsible for that. A build tool should deal with 
> single files and a package manager should deal with packages (of files).
>

Those are just there as examples. You can do it however you want.


-------------------------------
Not sent from an iPhone.




More information about the Digitalmars-d mailing list