github.com/wawandco/ox@v0.13.6-0.20230809142027-913b3d837f2a/plugins/tools/standard/build.go (about)

     1  package standard
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"os/exec"
     7  
     8  	"github.com/spf13/pflag"
     9  	"github.com/wawandco/ox/internal/info"
    10  	"github.com/wawandco/ox/plugins/core"
    11  )
    12  
    13  var (
    14  	// These are the interfaces we know that this
    15  	// plugin must satisfy for its correct functionality
    16  	_ core.Plugin     = (*Builder)(nil)
    17  	_ core.FlagParser = (*Builder)(nil)
    18  )
    19  
    20  type Builder struct {
    21  	output    string
    22  	buildTags []string
    23  	static    bool
    24  	flags     *pflag.FlagSet
    25  }
    26  
    27  func (b Builder) Name() string {
    28  	return "standard/builder"
    29  }
    30  
    31  // Build runs the Go compiler to generate the desired binary. Assuming the
    32  // Go executable installed and can be invoked with `go`.
    33  func (g *Builder) Build(ctx context.Context, root string, args []string) error {
    34  	buildArgs, err := g.composeBuildArgs()
    35  	if err != nil {
    36  		return err
    37  	}
    38  
    39  	cmd := exec.CommandContext(ctx, "go", buildArgs...)
    40  	cmd.Stderr = os.Stderr
    41  	cmd.Stdout = os.Stdout
    42  	cmd.Stdin = os.Stdin
    43  
    44  	return cmd.Run()
    45  }
    46  
    47  // ParseFlags
    48  func (b *Builder) ParseFlags(args []string) {
    49  	b.flags = pflag.NewFlagSet(b.Name(), pflag.ContinueOnError)
    50  	b.flags.Usage = func() {}
    51  	b.flags.StringVarP(&b.output, "output", "o", "", "the path the binary will be generated at")
    52  	b.flags.StringSliceVarP(&b.buildTags, "tags", "", []string{}, "tags to pass the go build command")
    53  	b.flags.BoolVar(&b.static, "static", true, `build a static binary using  --ldflags '-linkmode external -extldflags "-static"'`)
    54  	b.flags.Parse(args) //nolint:errcheck,we don't care hence the flag
    55  }
    56  
    57  // ParseFlags
    58  func (b *Builder) Flags() *pflag.FlagSet {
    59  	return b.flags
    60  }
    61  
    62  func (g *Builder) composeBuildArgs() ([]string, error) {
    63  	name, err := info.BuildName()
    64  	if err != nil {
    65  		return []string{}, err
    66  	}
    67  
    68  	buildArgs := []string{
    69  		"build",
    70  	}
    71  
    72  	//static
    73  	static := []string{
    74  		"--ldflags",
    75  		"-linkmode external",
    76  		"--ldflags",
    77  		`-extldflags "-static"`,
    78  	}
    79  
    80  	if g.static {
    81  		buildArgs = append(buildArgs, static...)
    82  	}
    83  
    84  	// output
    85  	o := []string{
    86  		"-o",
    87  		g.binaryOutput(name),
    88  	}
    89  	buildArgs = append(buildArgs, o...)
    90  
    91  	// add the build tags
    92  	if len(g.buildTags) != 0 {
    93  		buildArgs = append(buildArgs, "-tags")
    94  		buildArgs = append(buildArgs, g.buildTags...)
    95  	}
    96  
    97  	buildArgs = append(buildArgs, "./cmd/"+name)
    98  
    99  	return buildArgs, nil
   100  }
   101  
   102  // binaryOutput considers the output passed to
   103  // use it or default to bin/name.
   104  func (g *Builder) binaryOutput(name string) string {
   105  	output := "bin/" + name
   106  	if g.output != "" {
   107  		output = g.output
   108  	}
   109  
   110  	return output
   111  }