github.com/wawandco/oxpecker@v1.5.7-0.20210910201653-5958d4afdd89/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/oxpecker/internal/info"
    10  	"github.com/wawandco/oxpecker/plugins"
    11  )
    12  
    13  var (
    14  	// These are the interfaces we know that this
    15  	// plugin must satisfy for its correct functionality
    16  	_ plugins.Plugin     = (*Builder)(nil)
    17  	_ plugins.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.StringVarP(&b.output, "output", "o", "", "the path the binary will be generated at")
    51  	b.flags.StringSliceVarP(&b.buildTags, "tags", "", []string{}, "tags to pass the go build command")
    52  	b.flags.BoolVar(&b.static, "static", true, `build a static binary using  --ldflags '-linkmode external -extldflags "-static"'`)
    53  	b.flags.Parse(args) //nolint:errcheck,we don't care hence the flag
    54  }
    55  
    56  // ParseFlags
    57  func (b *Builder) Flags() *pflag.FlagSet {
    58  	return b.flags
    59  }
    60  
    61  func (g *Builder) composeBuildArgs() ([]string, error) {
    62  	name, err := info.BuildName()
    63  	if err != nil {
    64  		return []string{}, err
    65  	}
    66  
    67  	buildArgs := []string{
    68  		"build",
    69  	}
    70  
    71  	//static
    72  	static := []string{
    73  		"--ldflags",
    74  		"-linkmode external",
    75  		"--ldflags",
    76  		`-extldflags "-static"`,
    77  	}
    78  
    79  	if g.static {
    80  		buildArgs = append(buildArgs, static...)
    81  	}
    82  
    83  	// output
    84  	o := []string{
    85  		"-o",
    86  		g.binaryOutput(name),
    87  	}
    88  	buildArgs = append(buildArgs, o...)
    89  
    90  	// add the build tags
    91  	if len(g.buildTags) != 0 {
    92  		buildArgs = append(buildArgs, "-tags")
    93  		buildArgs = append(buildArgs, g.buildTags...)
    94  	}
    95  
    96  	buildArgs = append(buildArgs, "./cmd/"+name)
    97  
    98  	return buildArgs, nil
    99  }
   100  
   101  // binaryOutput considers the output passed to
   102  // use it or default to bin/name.
   103  func (g *Builder) binaryOutput(name string) string {
   104  	output := "bin/" + name
   105  	if g.output != "" {
   106  		output = g.output
   107  	}
   108  
   109  	return output
   110  }