@@ -5,6 +5,7 @@ package magesrc
55
66import (
77 "errors"
8+ "strings"
89
910 "github.com/magefile/mage/mg"
1011 "github.com/magefile/mage/sh"
@@ -17,7 +18,9 @@ var ErrSrcCode = errors.New("source code generation failed")
1718func Generate () error {
1819 mageutil .MagePrintln (mageutil .MsgStart , "Running code generation..." )
1920
20- err := sh .Run (mg .GoCmd (), "generate" , "./..." )
21+ // We run code generation for all packages in parallel, up to the number of CPU cores.
22+ // This saves meaningful time now that we have many packages with code generation.
23+ err := generateForAllPackagesInParallel ()
2124 if err != nil {
2225 return mageutil .PrintAndReturnError ("Code generation failed." , ErrSrcCode , err )
2326 }
@@ -26,3 +29,42 @@ func Generate() error {
2629
2730 return nil
2831}
32+
33+ func generateForAllPackagesInParallel () error {
34+ paths , err := listPackages ()
35+ if err != nil {
36+ return err
37+ }
38+
39+ generateDeps := []interface {}{}
40+
41+ // Build up a list of dependencies to run in parallel; we'll let [mg.Deps] take care of
42+ // the parallel execution.
43+ for _ , path := range paths {
44+ generateDeps = append (generateDeps , mg .F (generateForPackage , path ))
45+ }
46+
47+ mg .Deps (generateDeps ... )
48+
49+ return nil
50+ }
51+
52+ // listPackages lists all Go packages in the current module.
53+ func listPackages () ([]string , error ) {
54+ out , err := sh .Output (mg .GoCmd (), "list" , "./..." )
55+ if err != nil {
56+ return nil , mageutil .PrintAndReturnError ("Failed to list Go packages." , ErrSrcCode , err )
57+ }
58+
59+ return strings .Split (strings .TrimSpace (out ), "\n " ), nil
60+ }
61+
62+ // generateForPackage runs code generation for a specific package.
63+ func generateForPackage (path string ) error {
64+ err := sh .Run (mg .GoCmd (), "generate" , path )
65+ if err != nil {
66+ return mageutil .PrintAndReturnError ("Code generation failed." , ErrSrcCode , err )
67+ }
68+
69+ return nil
70+ }
0 commit comments