View mode: basic / threaded / horizontal-split · Log in · Help
July 15, 2011
Re: Prototype buildsystem "Drake"
"Jacob Carlborg" <doob@me.com> wrote in message 
news:ivp0rm$3lq$2@digitalmars.com...
> On 2011-07-14 21:18, Nick Sabalausky wrote:
>> "Jacob Carlborg"<doob@me.com>  wrote in message
>> news:ivnfk8$2v3p$1@digitalmars.com...
>>> On 2011-07-13 23:03, jdrewsen wrote:
>>>>
>>>> A good start I think. The first thing that I think should be fixed is
>>>> the naming.
>>>>
>>>> Drake should be called dbuild
>>>> Orb should be called dpack
>>>>
>>>> You read the name and you have an idea of what it does - nothing fancy.
>>>
>>> "Drake" was probably chosen because it's basically "rake for D" and
>>> possibly because "dake" was already taken. "rake" was most likely chosen
>>> because it's "make" but the makefiles are written in Ruby instead.
>>>
>>> I chose "Orbit" as the name of the package manager and named the tool
>>> "Orb". Why? No particular reason, but after that someone mentioned it 
>>> has
>>> the same theme as (Digital)Mars and Phobos.
>>>
>>
>> Between "Orb" and "Orange" I was thinking you just liked using names 
>> based
>> on round things :)
>
> Hehe. I actually started using names of fruits for my projects (I have an 
> unreleased library named "lime"), don't really know why I chose Orbit.
>

Fan of the Mango project? ;)
July 16, 2011
Re: Prototype buildsystem "Drake"
On 2011-07-16 00:07, Nick Sabalausky wrote:
> "Jacob Carlborg"<doob@me.com>  wrote in message
> news:ivp0oa$3lq$1@digitalmars.com...
>> On 2011-07-14 21:15, Nick Sabalausky wrote:
>>
>> Ah, now I see. I'm hoping the user never needs to write import statements
>> in the build script. It's just these little things that I don't like about
>> using D for the build scripts. Imports and no top level code.
>>
>
> I agree that the default imports should be sufficient for most typical uses.
> But it should be possible to create and share a Drake add-on in the form of
> a simple module to be imported. An import would be needed for that. Plus,
> even without Drake add-ons, it's reasonable to think that some people may
> have reason to import something from Phobos, or something from their own
> project, that wouldn't normally be used in most other buildscripts.

Absolutely, imports will be needed.

-- 
/Jacob Carlborg
July 16, 2011
Re: Prototype buildsystem "Drake"
On 2011-07-16 00:11, Nick Sabalausky wrote:
> "Jacob Carlborg"<doob@me.com>  wrote in message
>> Hehe. I actually started using names of fruits for my projects (I have an
>> unreleased library named "lime"), don't really know why I chose Orbit.
>>
>
> Fan of the Mango project? ;)

Hehe, I've actually never used it. But probably there I got the initial 
idea. It can be so hard to name a library/tool, so why not just take a 
simple word that doesn't say anything about the actual tool and be done 
with it.

-- 
/Jacob Carlborg
July 16, 2011
Re: Prototype buildsystem "Drake"
Jacob Carlborg wrote:
> On 2011-07-15 17:16, Andrei Alexandrescu wrote:
>> On 7/15/11 7:58 AM, Jacob Carlborg wrote:
>>> I'm not very familiar with Scala but I found this:
>>> http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/
>>>
>>
>> Interesting. What are the features that do make a DSL better looking in
>> Scala than in D?
>>
>>
>> Thanks,
>>
>> Andrei
>
> This is just what I think (I've thrown in Ruby and CoffeeScript as well)
>
> Scala:
>
> * Delegate syntax - Scala allows passing a delegate to a syntax like this:
>
> loop {
>     // code
> }
>
> This allows to create, what look likes, new statements. I don't recall
> how the "loop" function should be implemented but it was quite complex
> and had something do with partial functions.
>
> Scala also has this nice delegate syntax:
>
> foo(a => a + a)
>
> * Infix operators - Allows to call any method that takes one argument
> without parentheses and without the dot:
>
> object.func("asd")
>
> Can be called like this:
>
> object func "asd"
>
> * Naming methods - In Scala you can name a method "+", "-", "*" and
> similar. You are not limited to A-Za-z_0-9. Together with infix
> operators this is how Scala implements operator overloading. This also
> allows to add new operators.
>
> * No semicolons
> * Is in general very good at inferring types, including return types
> * Almost everything is an expression
> * The constructor is built-in the class declaration:
>
> class Foo
> {
>      // this is the constructor
>      def foo = "foo"
> }

One of the more important features you didn't mention are the so-called
"implicits". Implicits are basically scoped implicit conversions, but strictly
more powerful: They can deduce the conversion function based on an extended
context, like the signature of a member function the resulting type should
provide. Eg:

class IntExtensions(i: Int){
     def times(j: Int) = i*j
}

implicit def intExtensions(i: Int) = new IntExtensions(i) // implicit conversion
of Int to IntExtensions
implicit def strToInt(s: String) = s match { // implicit conversion from String to Int
        case "one" => 1
        case "two" => 2
        case "three" => 3
        //...
        case _ => throw new Exception("Unknown number " + s)
}
implicit def intExtensions(s: String) = new IntExtensions(strToInt(s)) // implicit
conversion from String to IntExtensions (implicits are not automagically
transitive, probably for compiler efficiency)


// now you can write stuff like (this also depends on infix operators):
val x="three" times "two" times	"one"
val y=3 times "two"
val z="three" times 2

assert(x==6 && y==6 && z==6);

If D had UFCS and infix operators, it would have a lot more power to build DSELs.
I don't know exactly how infix operators would play with Ds somewhat ambiguous
declaration syntax.
Of course, there are always string mixins, but then you are departing from valid D
syntax with your DSL.

mixin(myDSLtoD(q{not D code}));
or
myDSL!q{not D code};


Cheers,
-Timon
July 16, 2011
Re: Prototype buildsystem "Drake"
"Jacob Carlborg" <doob@me.com> wrote in message 
news:ivrm1t$1f20$2@digitalmars.com...
> On 2011-07-16 00:11, Nick Sabalausky wrote:
>> "Jacob Carlborg"<doob@me.com>  wrote in message
>>> Hehe. I actually started using names of fruits for my projects (I have 
>>> an
>>> unreleased library named "lime"), don't really know why I chose Orbit.
>>>
>>
>> Fan of the Mango project? ;)
>
> Hehe, I've actually never used it. But probably there I got the initial 
> idea. It can be so hard to name a library/tool, so why not just take a 
> simple word that doesn't say anything about the actual tool and be done 
> with it.
>

That's a good point. I agonize over project names far too much.
July 17, 2011
Re: Prototype buildsystem "Drake"
On 2011-07-16 15:24, Timon Gehr wrote:
> Jacob Carlborg wrote:
>> On 2011-07-15 17:16, Andrei Alexandrescu wrote:
>>> On 7/15/11 7:58 AM, Jacob Carlborg wrote:
>>>> I'm not very familiar with Scala but I found this:
>>>> http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/
>>>>
>>>
>>> Interesting. What are the features that do make a DSL better looking in
>>> Scala than in D?
>>>
>>>
>>> Thanks,
>>>
>>> Andrei
>>
>> This is just what I think (I've thrown in Ruby and CoffeeScript as well)
>>
>> Scala:
>>
>> * Delegate syntax - Scala allows passing a delegate to a syntax like this:
>>
>> loop {
>>      // code
>> }
>>
>> This allows to create, what look likes, new statements. I don't recall
>> how the "loop" function should be implemented but it was quite complex
>> and had something do with partial functions.
>>
>> Scala also has this nice delegate syntax:
>>
>> foo(a =>  a + a)
>>
>> * Infix operators - Allows to call any method that takes one argument
>> without parentheses and without the dot:
>>
>> object.func("asd")
>>
>> Can be called like this:
>>
>> object func "asd"
>>
>> * Naming methods - In Scala you can name a method "+", "-", "*" and
>> similar. You are not limited to A-Za-z_0-9. Together with infix
>> operators this is how Scala implements operator overloading. This also
>> allows to add new operators.
>>
>> * No semicolons
>> * Is in general very good at inferring types, including return types
>> * Almost everything is an expression
>> * The constructor is built-in the class declaration:
>>
>> class Foo
>> {
>>       // this is the constructor
>>       def foo = "foo"
>> }
>
> One of the more important features you didn't mention are the so-called
> "implicits". Implicits are basically scoped implicit conversions, but strictly
> more powerful: They can deduce the conversion function based on an extended
> context, like the signature of a member function the resulting type should
> provide. Eg:
>
> class IntExtensions(i: Int){
>        def times(j: Int) = i*j
> }
>
> implicit def intExtensions(i: Int) = new IntExtensions(i) // implicit conversion
> of Int to IntExtensions
> implicit def strToInt(s: String) = s match { // implicit conversion from String to Int
>           case "one" =>  1
>           case "two" =>  2
>           case "three" =>  3
>           //...
>           case _ =>  throw new Exception("Unknown number " + s)
> }
> implicit def intExtensions(s: String) = new IntExtensions(strToInt(s)) // implicit
> conversion from String to IntExtensions (implicits are not automagically
> transitive, probably for compiler efficiency)
>
>
> // now you can write stuff like (this also depends on infix operators):
> val x="three" times "two" times	"one"
> val y=3 times "two"
> val z="three" times 2
>
> assert(x==6&&  y==6&&  z==6);

Yeah, implicits are nice as well.

> If D had UFCS and infix operators, it would have a lot more power to build DSELs.
> I don't know exactly how infix operators would play with Ds somewhat ambiguous
> declaration syntax.
> Of course, there are always string mixins, but then you are departing from valid D
> syntax with your DSL.
>
> mixin(myDSLtoD(q{not D code}));
> or
> myDSL!q{not D code};
>
>
> Cheers,
> -Timon

String mixins are not a solution to DSLs in my opinion.

-- 
/Jacob Carlborg
July 17, 2011
Re: Prototype buildsystem "Drake"
"Jacob Carlborg" <doob@me.com> wrote in message 
news:ivp1gd$500$2@digitalmars.com...
> On 2011-07-14 21:50, Nick Sabalausky wrote:
>> "Jacob Carlborg"<doob@me.com>  wrote in message
>> news:ivng77$305d$1@digitalmars.com...
>>> On 2011-07-13 23:52, Nick Sabalausky wrote:
>>>> Hmm, yea, configure didn't even occur to me. I think it could acually 
>>>> be
>>>> done as just another File target that everything else depends on. Only
>>>> thing
>>>> is then you'd have to save/load the configuration file manually, so 
>>>> maybe
>>>> there should be some convenience mechnism for that (Maybe utilizing
>>>> Jacob's
>>>> Orange serialization library once that rewrite is done? Or maybe that
>>>> would
>>>> be overkill? Is there some INI-file util, or am I just imagining that?)
>>>
>>> What about doing something like DSSS/rebuild does. There are config 
>>> files
>>> for dmd, ldc and gdc on various platforms. You can choose to invoke
>>> different compilers and it will use the config file for that particular
>>> compiler on the current platform.
>>>
>>
>> One of my main goals for Drake is that using any old random tool (besides
>> just building D code) doesn't feel like an afterthought. That
>> DSSS/rebuild-style approach doesn't seem like it would scale particularly
>> well in that direction. I think whatever solution is used needs to work 
>> just
>> as well for the user's own custom tools as it does for DMD/LDC/GDC. Then,
>> any D-specific simplifications/improvements that are made should be built 
>> on
>> top of that. For example, we could provide a function the user calls from
>> within their "configure" step that automatically handles D-specific
>> configuring (And yea, maybe we could even automatically provide a default
>> "configure" that already calls that function.)
>
> Ok, have you thought about how this will look (in code) and behave?
>

Not extensively, but here's what I have in mind so far. In an early initial 
version of Drake, it would be like this:

   task("configure", "drake.conf");

   file("drake.conf",
       (Target t)
       {
           // Do all configuring here and save to drake.conf
       }
   );

Then, Drake can add built-in tools for configuring DMD and saving/loading a 
configuation file:

   task("configure", "drake.conf");

   file("drake.conf",
       (Target t)
       {
           auto configure = configureDMD();

           // Do all custom configuring (if any) here,
           // adding data to be saved into 'configure'.

           configure.save(t.name);
       }
   );

And finally, all that boilerplate can be hidden away and handled 
automatically by Drake:

   // Completely optional:
   file("drake.conf",
       (Target t)
       {
           // Do all custom configuring here (if any is even desired),
           // adding data to be saved into global 'configure'.
       }
   );

At that point, the automatic configuring could optionally be disabled like 
this:

   defaultConfigure = false;

   // Completely optional, completely manual:

   task("configure", "drake.conf");
   file("drake.conf",
       (Target t)
       {
           // Do all configuring here and save to drake.conf.
           // The 'configureDMD' and 'configure' can still be
           // used manually.
       }
   );
July 18, 2011
Re: Prototype buildsystem "Drake"
On 2011-07-17 23:01, Nick Sabalausky wrote:
> "Jacob Carlborg"<doob@me.com>  wrote in message
>> Ok, have you thought about how this will look (in code) and behave?
>>
>
> Not extensively, but here's what I have in mind so far. In an early initial
> version of Drake, it would be like this:
>
>      task("configure", "drake.conf");
>
>      file("drake.conf",
>          (Target t)
>          {
>              // Do all configuring here and save to drake.conf
>          }
>      );

Ok. Will the build script change the configuration file? Seems kind of 
strange. Usually the config file is used to control the build script, 
not the other way around.

-- 
/Jacob Carlborg
July 18, 2011
Re: Re Build tools for D [ was Re: Prototype buildsystem "Drake"]
When writing Haskell and compiling with GHC, the compiler automatically
finds the module dependencies and compiles them in the correct order.  If I
touch a few modules and recompile, GHC will only recompile the touched
modules as appropriate, then re-link.  In other words, GHC is the build tool
as well as the compiler.  The advantages of this approach over having a
separate build tool are:

- the compiler already knows how to parse module files, so it's in the
perfect position to know what the dependencies are.  We don't have some
hacky extra tool sniffing out lines that look like "import X;".  This alone
seems error-prone, but more importantly, D modules can have arbitrary
compile-time logic executed before importing something, so the build tool
essentially either has to give up or reimplement the compiler to cover all
cases.  (This is the primary reason I advocate this approach -- I don't see
how a generic build tool can automatically detect dependencies without the
participation of a D compiler.)
- the steps to compile a one-file program are exactly the same as compiling
a complex multi-module program: "ghc Main".  If I split out one file into
several, I don't have to immediately switch to using Make/waf/etc; it will
Just Work.  There's one less tool to remember, and once you've got your D
compiler, you're all set.

On Wed, Jul 13, 2011 at 7:28 PM, Jacob Carlborg <doob@me.com> wrote:

> On 2011-07-13 19:27, Jonathan M Davis wrote:
>
>> On 2011-07-13 08:36, Jacob Carlborg wrote:
>>
>>> On 2011-07-13 07:28, Jonathan M Davis wrote:
>>>
>>>> On Wednesday 13 July 2011 06:12:58 Russel Winder wrote:
>>>>
>>>>> And, of course, I should have mentioned CMake and CMakeD.
>>>>>
>>>>> The fact that I forgot, shows my prejudice against Makefile-based
>>>>> systems and for direct DAG-based systems such as Gradle, SCons and Waf.
>>>>> This though should not stop CMakeD being a part of this debate.
>>>>>
>>>>>  From previous discussions, it seems that one of the primary reasons
>>>>> for
>>>>> having
>>>>>
>>>>
>>>> a D build tool in many people's minds is to also handle package
>>>> management of D libraries (like Haskell's cabal or rubygems for ruby).
>>>> And as great as cmaked, scons, gradle, waf, and other such tools may be,
>>>> they don't do that.
>>>>
>>>> - Jonathan M Davis
>>>>
>>>
>>> I don't agree with that. I think a build tool should deal with single
>>> files and building. A package manager should deal with packages (of
>>> files). In Ruby, RubyGems is the package manager and Rake is the build
>>> tool.
>>>
>>
>> Well, I'm not advocating anything in particular. I was just pointing out
>> that
>> a big part of the discussions on build tools has been package management
>> of
>> libraries, and any build tool solution which doesn't at least integrate
>> with
>> some sort of package management solution is likely to not be what at least
>> some people are looking for.
>>
>
> Ok, I see. I think as well that the build tool and package manager should
> interact with each other. For example, specifying package dependencies in
> the build script. But, I think they need to be separate and be usable on
> their own.
>
>  Personally, I don't generally use package management tools for handling
>> libraries even with languages that have such tools, and I don't generally
>> use
>> much in the way of build tools either beyond simple scripts (primarily
>> because
>> I don't generally have projects large enough for it to be an issue). As it
>> stands, if I were to choose a build tool for a larger project, I'd
>> probably
>> choose CmakeD, but I'm not super-familiar with all of the tools out there
>> and
>> haven't generally found much use for them.
>>
>> I was just trying to point out that a fair bit of the discussion for such
>> tools in this list has related to package management, and Nick's solution
>> doesn't address that at all AFAIK.
>>
>> - Jonathan m Davis
>>
>
> Ok, I see.
>
> --
> /Jacob Carlborg
>
July 18, 2011
Re: Re Build tools for D [ was Re: Prototype buildsystem "Drake"]
On 2011-07-18 19:37, James Fisher wrote:
> When writing Haskell and compiling with GHC, the compiler automatically
> finds the module dependencies and compiles them in the correct order.
>   If I touch a few modules and recompile, GHC will only recompile the
> touched modules as appropriate, then re-link.  In other words, GHC is
> the build tool as well as the compiler.  The advantages of this approach
> over having a separate build tool are:
>
> - the compiler already knows how to parse module files, so it's in the
> perfect position to know what the dependencies are.  We don't have some
> hacky extra tool sniffing out lines that look like "import X;".  This
> alone seems error-prone, but more importantly, D modules can have
> arbitrary compile-time logic executed before importing something, so the
> build tool essentially either has to give up or reimplement the compiler
> to cover all cases.  (This is the primary reason I advocate this
> approach -- I don't see how a generic build tool can automatically
> detect dependencies without the participation of a D compiler.)
> - the steps to compile a one-file program are exactly the same as
> compiling a complex multi-module program: "ghc Main".  If I split out
> one file into several, I don't have to immediately switch to using
> Make/waf/etc; it will Just Work.  There's one less tool to remember, and
> once you've got your D compiler, you're all set.

With DMD you can use the -deps flag to get all the dependencies of all 
specified files. No reason to try to parse import statements.

Can GHC compiler other types than executables, i.e. libraries?

-- 
/Jacob Carlborg
5 6 7 8 9 10 11 12
Top | Discussion index | About this forum | D home