github.com/tiagovtristao/plz@v13.4.0+incompatible/src/plz/plz.go (about)

     1  package plz
     2  
     3  import (
     4  	"sync"
     5  
     6  	"gopkg.in/op/go-logging.v1"
     7  
     8  	"github.com/thought-machine/please/src/build"
     9  	"github.com/thought-machine/please/src/cli"
    10  	"github.com/thought-machine/please/src/core"
    11  	"github.com/thought-machine/please/src/follow"
    12  	"github.com/thought-machine/please/src/fs"
    13  	"github.com/thought-machine/please/src/metrics"
    14  	"github.com/thought-machine/please/src/parse"
    15  	"github.com/thought-machine/please/src/test"
    16  	"github.com/thought-machine/please/src/utils"
    17  )
    18  
    19  var log = logging.MustGetLogger("plz")
    20  
    21  // Run runs a build to completion.
    22  // The given state object controls most of the parameters to it and can be interrogated
    23  // afterwards to find success / failure.
    24  // To get detailed results as it runs, use state.Results. You should call that *before*
    25  // starting this (otherwise a sufficiently fast build may bypass you completely).
    26  func Run(targets, preTargets []core.BuildLabel, state *core.BuildState, config *core.Configuration, arch cli.Arch) {
    27  	parse.InitParser(state)
    28  	build.Init(state)
    29  
    30  	if config.Events.Port != 0 && state.NeedBuild {
    31  		shutdown := follow.InitialiseServer(state, config.Events.Port)
    32  		defer shutdown()
    33  	}
    34  	if config.Events.Port != 0 || config.Display.SystemStats {
    35  		go follow.UpdateResources(state)
    36  	}
    37  	metrics.InitFromConfig(config)
    38  
    39  	// Start looking for the initial targets to kick the build off
    40  	go findOriginalTasks(state, preTargets, targets, arch)
    41  	// Start up all the build workers
    42  	var wg sync.WaitGroup
    43  	wg.Add(config.Please.NumThreads)
    44  	for i := 0; i < config.Please.NumThreads; i++ {
    45  		go func(tid int) {
    46  			doTasks(tid, state, state.Include, state.Exclude, arch)
    47  			wg.Done()
    48  		}(i)
    49  	}
    50  	// Wait until they've all exited, which they'll do once they have no tasks left.
    51  	wg.Wait()
    52  	if state.Cache != nil {
    53  		state.Cache.Shutdown()
    54  	}
    55  }
    56  
    57  func doTasks(tid int, state *core.BuildState, include, exclude []string, arch cli.Arch) {
    58  	for {
    59  		label, dependor, t := state.NextTask()
    60  		switch t {
    61  		case core.Stop, core.Kill:
    62  			return
    63  		case core.Parse, core.SubincludeParse:
    64  			t := t
    65  			label := label
    66  			dependor := dependor
    67  			state.ParsePool <- func() {
    68  				parse.Parse(tid, state, label, dependor, include, exclude, t == core.SubincludeParse)
    69  				state.TaskDone(false)
    70  			}
    71  		case core.Build, core.SubincludeBuild:
    72  			build.Build(tid, state, label)
    73  			state.TaskDone(true)
    74  		case core.Test:
    75  			test.Test(tid, state, label)
    76  			state.TaskDone(true)
    77  		}
    78  	}
    79  }
    80  
    81  // findOriginalTasks finds the original parse tasks for the original set of targets.
    82  func findOriginalTasks(state *core.BuildState, preTargets, targets []core.BuildLabel, arch cli.Arch) {
    83  	if state.Config.Bazel.Compatibility && fs.FileExists("WORKSPACE") {
    84  		// We have to parse the WORKSPACE file before anything else to understand subrepos.
    85  		// This is a bit crap really since it inhibits parallelism for the first step.
    86  		parse.Parse(0, state, core.NewBuildLabel("workspace", "all"), core.OriginalTarget, state.Include, state.Exclude, false)
    87  	}
    88  	if arch.Arch != "" {
    89  		// Set up a new subrepo for this architecture.
    90  		state.Graph.AddSubrepo(core.SubrepoForArch(state, arch))
    91  	}
    92  	if len(preTargets) > 0 {
    93  		findOriginalTaskSet(state, preTargets, false, arch)
    94  		for _, target := range preTargets {
    95  			log.Debug("Waiting for pre-target %s...", target)
    96  			state.WaitForBuiltTarget(target, targets[0])
    97  			log.Debug("Pre-target %s built, continuing...", target)
    98  		}
    99  	}
   100  	findOriginalTaskSet(state, targets, true, arch)
   101  	state.TaskDone(true) // initial target adding counts as one.
   102  }
   103  
   104  func findOriginalTaskSet(state *core.BuildState, targets []core.BuildLabel, addToList bool, arch cli.Arch) {
   105  	for _, target := range targets {
   106  		if target == core.BuildLabelStdin {
   107  			for label := range cli.ReadStdin() {
   108  
   109  				findOriginalTask(state, core.ParseBuildLabels([]string{label})[0], addToList, arch)
   110  			}
   111  		} else {
   112  			findOriginalTask(state, target, addToList, arch)
   113  		}
   114  	}
   115  }
   116  
   117  func findOriginalTask(state *core.BuildState, target core.BuildLabel, addToList bool, arch cli.Arch) {
   118  	if arch.Arch != "" {
   119  		target.Subrepo = arch.String()
   120  	}
   121  	if target.IsAllSubpackages() {
   122  		for pkg := range utils.FindAllSubpackages(state.Config, target.PackageName, "") {
   123  			state.AddOriginalTarget(core.NewBuildLabel(pkg, "all"), addToList)
   124  		}
   125  	} else {
   126  		state.AddOriginalTarget(target, addToList)
   127  	}
   128  }