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 }