gitee.com/mirrors_opencollective/goreleaser@v0.45.0/pipeline/build/checkmain.go (about)

     1  package build
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/parser"
     7  	"go/token"
     8  	"os"
     9  
    10  	"github.com/goreleaser/goreleaser/config"
    11  	"github.com/goreleaser/goreleaser/context"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  func checkMain(ctx *context.Context, build config.Build) error {
    16  	var main = build.Main
    17  	if main == "" {
    18  		main = "."
    19  	}
    20  	stat, ferr := os.Stat(main)
    21  	if os.IsNotExist(ferr) {
    22  		return errors.Wrapf(ferr, "could not open %s", main)
    23  	}
    24  	if stat.IsDir() {
    25  		packs, err := parser.ParseDir(token.NewFileSet(), main, nil, 0)
    26  		if err != nil {
    27  			return errors.Wrapf(err, "failed to parse dir: %s", main)
    28  		}
    29  		for _, pack := range packs {
    30  			for _, file := range pack.Files {
    31  				if hasMain(file) {
    32  					return nil
    33  				}
    34  			}
    35  		}
    36  		return fmt.Errorf("build for %s does not contain a main function", build.Binary)
    37  	}
    38  	file, err := parser.ParseFile(token.NewFileSet(), build.Main, nil, 0)
    39  	if err != nil {
    40  		return errors.Wrapf(err, "failed to parse file: %s", build.Main)
    41  	}
    42  	if hasMain(file) {
    43  		return nil
    44  	}
    45  	return fmt.Errorf("build for %s does not contain a main function", build.Binary)
    46  }
    47  
    48  func hasMain(file *ast.File) bool {
    49  	for _, decl := range file.Decls {
    50  		fn, isFn := decl.(*ast.FuncDecl)
    51  		if !isFn {
    52  			continue
    53  		}
    54  		if fn.Name.Name == "main" && fn.Recv == nil {
    55  			return true
    56  		}
    57  	}
    58  	return false
    59  }