github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/cmd/gogio/build_info.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"path"
     9  	"path/filepath"
    10  	"runtime"
    11  	"strings"
    12  )
    13  
    14  type buildInfo struct {
    15  	appID    string
    16  	archs    []string
    17  	ldflags  string
    18  	minsdk   int
    19  	name     string
    20  	pkgDir   string
    21  	pkgPath  string
    22  	iconPath string
    23  	tags     string
    24  	target   string
    25  	version  int
    26  	key      string
    27  	password string
    28  }
    29  
    30  func newBuildInfo(pkgPath string) (*buildInfo, error) {
    31  	pkgMetadata, err := getPkgMetadata(pkgPath)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	appID := getAppID(pkgMetadata)
    36  	appIcon := filepath.Join(pkgMetadata.Dir, "appicon.png")
    37  	if *iconPath != "" {
    38  		appIcon = *iconPath
    39  	}
    40  	bi := &buildInfo{
    41  		appID:    appID,
    42  		archs:    getArchs(),
    43  		ldflags:  getLdFlags(appID),
    44  		minsdk:   *minsdk,
    45  		name:     getPkgName(pkgMetadata),
    46  		pkgDir:   pkgMetadata.Dir,
    47  		pkgPath:  pkgPath,
    48  		iconPath: appIcon,
    49  		tags:     *extraTags,
    50  		target:   *target,
    51  		version:  *version,
    52  		key:      *signKey,
    53  		password: *signPass,
    54  	}
    55  	return bi, nil
    56  }
    57  
    58  func getArchs() []string {
    59  	if *archNames != "" {
    60  		return strings.Split(*archNames, ",")
    61  	}
    62  	switch *target {
    63  	case "js":
    64  		return []string{"wasm"}
    65  	case "ios", "tvos":
    66  		// Only 64-bit support.
    67  		return []string{"arm64", "amd64"}
    68  	case "android":
    69  		return []string{"arm", "arm64", "386", "amd64"}
    70  	case "windows":
    71  		goarch := os.Getenv("GOARCH")
    72  		if goarch == "" {
    73  			goarch = runtime.GOARCH
    74  		}
    75  		return []string{goarch}
    76  	default:
    77  		// TODO: Add flag tests.
    78  		panic("The target value has already been validated, this will never execute.")
    79  	}
    80  }
    81  
    82  func getLdFlags(appID string) string {
    83  	var ldflags []string
    84  	if extra := *extraLdflags; extra != "" {
    85  		ldflags = append(ldflags, strings.Split(extra, " ")...)
    86  	}
    87  	// Pass appID along, to be used for logging on platforms like Android.
    88  	ldflags = append(ldflags, fmt.Sprintf("-X github.com/cybriq/giocore/app/internal/log.appID=%s", appID))
    89  	// Pass along all remaining arguments to the app.
    90  	if appArgs := flag.Args()[1:]; len(appArgs) > 0 {
    91  		ldflags = append(ldflags, fmt.Sprintf("-X github.com/cybriq/giocore/app.extraArgs=%s", strings.Join(appArgs, "|")))
    92  	}
    93  	if m := *linkMode; m != "" {
    94  		ldflags = append(ldflags, "-linkmode="+m)
    95  	}
    96  	return strings.Join(ldflags, " ")
    97  }
    98  
    99  type packageMetadata struct {
   100  	PkgPath string
   101  	Dir     string
   102  }
   103  
   104  func getPkgMetadata(pkgPath string) (*packageMetadata, error) {
   105  	pkgImportPath, err := runCmd(exec.Command("go", "list", "-f", "{{.ImportPath}}", pkgPath))
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	pkgDir, err := runCmd(exec.Command("go", "list", "-f", "{{.Dir}}", pkgPath))
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	return &packageMetadata{
   114  		PkgPath: pkgImportPath,
   115  		Dir:     pkgDir,
   116  	}, nil
   117  }
   118  
   119  func getAppID(pkgMetadata *packageMetadata) string {
   120  	if *appID != "" {
   121  		return *appID
   122  	}
   123  	elems := strings.Split(pkgMetadata.PkgPath, "/")
   124  	domain := strings.Split(elems[0], ".")
   125  	name := ""
   126  	if len(elems) > 1 {
   127  		name = "." + elems[len(elems)-1]
   128  	}
   129  	if len(elems) < 2 && len(domain) < 2 {
   130  		name = "." + domain[0]
   131  		domain[0] = "localhost"
   132  	} else {
   133  		for i := 0; i < len(domain)/2; i++ {
   134  			opp := len(domain) - 1 - i
   135  			domain[i], domain[opp] = domain[opp], domain[i]
   136  		}
   137  	}
   138  
   139  	pkgDomain := strings.Join(domain, ".")
   140  	appid := []rune(pkgDomain + name)
   141  
   142  	// a Java-language-style package name may contain upper- and lower-case
   143  	// letters and underscores with individual parts separated by '.'.
   144  	// https://developer.android.com/guide/topics/manifest/manifest-element
   145  	for i, c := range appid {
   146  		if !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' ||
   147  			c == '_' || c == '.') {
   148  			appid[i] = '_'
   149  		}
   150  	}
   151  	return string(appid)
   152  }
   153  
   154  func getPkgName(pkgMetadata *packageMetadata) string {
   155  	return path.Base(pkgMetadata.PkgPath)
   156  }