Thanks for all the great feedback on skip proposal:
  
http://www.nabble.com/Some-ideas-on-path-handling-and-our-command-line-td21768085.html

  Lately, I've been working another notion: specifying targets via groovy 
  regex on the command line.  This could be nice in cases where you 
  don't want to make a bunch of stupid ephemeral targets for ad-hoc 
  target collections (this can be heplful during testing).  The regex 
  idea isn't very complicated but I wanted to play with a few different 
  possibilities before asking anybody to look at it in detail.

  For that reason, instead of talking about target regexes, 
  I'd like to raise an issue that occurred to me along the way:
  should targets on the command line be treated as "build goals"
  or as a series "actions" for Gradle to preform?

  Concretely, should the following commands be equivalent or not?
  
                 %  gradle  cow 
                 %  gradle  cow cow cow

  Gnu Make says:  Yes; the second command just redundantly states a goal.
  Ant says:       No;  the second command means "execute 'cow' three times".

  Currently, Gradle does things Ant's way.
  I believe Gradle should handle it Make's way.

  At first I thought this subtle distinction really didn't matter all 
  that much, but now I do:  I think "build goal" semantics (like Make) 
  are preferable to "build action" semantics (like Ant).  Besides being 
  more predictable when it comes to specification via regex, Make's "goal" 
  semantics for targets lead to greater symmetry in terms of Gradle's
  DAG-oriented design, and scale better in terms of human understanding
  in cases where the build is complex & tasks aren't idempotent.

  I'd be very interested in hearing what others think about this issue.


                        Cheers,
                        -Jon

 --------------------------------------------------------------------
 Gory Details:
 --------------------------------------------------------------------

        Suppose 
                task moo dependsOn cow
                task egg dependsOn cow
                task cow does not depend on anything
 
        If we say:

                 %  gradle  cow cow cow

        Currently, in Gradle that means:

                run the cow task
                then run the cow task again
                then run the cow task yet again

        I believe this should mean "run cow once",   
        and be entirely equivalent to: 

                 %  gradle  cow

        You could argue either way about the issuance of a warning.
        Here are the things I think are worth considering:
         
         [1]  Historical precedent:  A mixed bag.
              Suppose you had the following Makefile:

                    #----------------------------
                        .PHONY=(cow)
                        cow:
                             echo you said cow
                    #----------------------------

                Then suppose you issued the command:
                     %  make  cow cow cow

               Gnu make would run cow once.
               However, suppose you have the following build.xml:

                    <!-- ~~~~~~~~~~~~~~~~~~~~~~~ -->
                    <project  default="all">
                        <target name="cow">
                             <echo>cow</echo>
                         </target>
                     </project>
                    <!-- ~~~~~~~~~~~~~~~~~~~~~~~ -->

                Then suppose you issued the command:
                     %  ant  cow cow cow

                Ant would run cow three times.

              Therefore, I think there isn't a particularly
              strong historical president argument either way.
              Two commonly-used programs do it differently.



         [2]  Consistency of metaphor
              When many tasks in a graph depend on cow, 
              cow only gets run once.   We don't run cow
              more than that because our goal was to build
              it, and once we've done that, we're done.
              Thus, it seems strange to say that we accept
              this reasoning when it comes to the DAG, but
              not when it comes to our command-line specification
              of what's to be built.  This argument seems to lean 
              in favor of the GNU-make's  "do it once" semantics.

              Put differently, GNU Make treats the command line as 
              indicating what your goals are, not like a crippled 
              scripting language.  Ant treats the command line 
              as a series of call sites (i.e.:  cow()  cow() cow()).
              Build systems are about goals, so the GNU make metaphor 
              seems to be upheld better by "do it once". 


         [3]  Symmetry of operations
              Consider what the following command SHOULD mean:

                  % gradle  moo -cow -cow -cow

              The user has indicated "they don't want cow".
              Pressing the elevator button over and over
              should not matter.  Ok already, I won't do cow!
              Therefore, it's currently (and correctly) 
              equivalent to:
              
                  % gradle  moo -cow 

              Let's see what gradle does under harsher conditions.
              Suppose we've got this build.gradle file:

                    createTask("moo", dependsOn: "fun") {}
                    createTask("cow", dependsOn: "fun") {}
                    createTask("fun")                   {}
                
              Look at what we get right now:

                    % gradle  -Dskip.fun  moo fun
                    :fun SKIPPED
                    :moo
                    :fun SKIPPED

              So far so good.
              We said we didn't want any 'fun' and so our wish was granted.
              Here's an easy one:

                    % gradle   moo    
                    :fun
                    :moo

              Fine, moo dependsOn fun so this is exactly what I'd expect.
              But now look at this:
                
                    % gradle   moo fun   
                    :fun
                    :moo
                    :fun

              Wait.  
              I'm all for doubling my pleasure, but should I *really* be 
              having this much fun?   The 'moo' task already implies the 
              'fun' task, but here I am running 'fun' twice, probably by 
              accident.   If 'fun' was a deeply-nested dependency of the 
              moo task, it's very easy for a person typing on the command
              line to not realize that.  I think you could even say that
              it's critical for scalability (on the dimension of complexity)
              that the user should NOT have to know that somewhere deep
              in the guts of the build that 'moo' eventually calls 'fun'.
              Hence, explicitly saying 'fun' on the command line should
              be harmlessly idempotent.  The task should only run once.

    Conclusion:
       While different from how Ant works, the GNU Make-ish
       "do it once" semantics seems preferable because it's:
       
          o  Easier for humans to predict the behavior of complex builds
             (e.g.: in the case of deep 'fun' task dependencies)

          o  More symmetric with how everybody agrees negated tasks work

          o  more congruent with the goal-oriented nature of a build system
             (i.e.: command lines should specify goals, not procedures).


       Just as the DAG spares me from running fun multiple times when more 
       than one thing depends on it, and just like I don't need to keep 
       saying "-Dskip.fun"  for each attempt to re-invoke 'fun', I don't
       think gradle should treat redundant targets in the command line
       as task invocations.   
       
       In short, I believe that:
       
                % gradle cow cow cow
        
        should mean:

                % gradle cow

        The fact that it's not working that way now seems like a bug,
        despite Ant's historical president.  Because there are fairly
        compelling reasons to work GNU Make's way, it's not just a
        matter of taste. I believe GNU got this one right.


                What do you think?
                -Jon


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to