diff --git a/gogio/help.go b/gogio/help.go index c6cd7f2..977bb99 100644 --- a/gogio/help.go +++ b/gogio/help.go @@ -65,7 +65,8 @@ its deletion. The -x flag will print all the external commands executed by the gogio tool. The -signkey flag specifies the path of the keystore, used for signing Android apk/aab files -or specifies the name of key on Keychain to sign MacOS app. +or specifies the name of key on Keychain to sign MacOS app. On iOS/macOS it can be used to +specify the path of provisioning profile (.mobileprovision/.provisionprofile). The -signpass flag specifies the password of the keystore, ignored if -signkey is not provided. diff --git a/gogio/iosbuild.go b/gogio/iosbuild.go index b6885ba..b13f9c6 100644 --- a/gogio/iosbuild.go +++ b/gogio/iosbuild.go @@ -77,7 +77,8 @@ func buildIOS(tmpDir, target string, bi *buildInfo) error { if err := exeIOS(tmpDir, target, appDir, bi); err != nil { return err } - if err := signIOS(bi, tmpDir, appDir); err != nil { + embedded := filepath.Join(appDir, "embedded.mobileprovision") + if err := signApple(bi, tmpDir, embedded, appDir); err != nil { return err } return zipDir(out, tmpDir, "Payload") @@ -86,16 +87,27 @@ func buildIOS(tmpDir, target string, bi *buildInfo) error { } } -func signIOS(bi *buildInfo, tmpDir, app string) error { +// signApple is shared between iOS and macOS. +func signApple(bi *buildInfo, tmpDir, embedded, app string) error { home, err := os.UserHomeDir() if err != nil { return err } - provPattern := filepath.Join(home, "Library", "MobileDevice", "Provisioning Profiles", "*.mobileprovision") - provisions, err := filepath.Glob(provPattern) - if err != nil { - return err + + var provisions []string + if bi.key != "" { + if filepath.Ext(bi.key) != ".mobileprovision" && filepath.Ext(bi.key) != ".provisionprofile" { + return fmt.Errorf("sign: on iOS/macOS -key is a provisioning profile, %q does not end in .mobileprovision/.provisionprofile", bi.key) + } + provisions = []string{bi.key} + } else { + provPattern := filepath.Join(home, "Library", "MobileDevice", "Provisioning Profiles", "*.mobileprovision") + provisions, err = filepath.Glob(provPattern) + if err != nil { + return err + } } + provInfo := filepath.Join(tmpDir, "provision.plist") var avail []string for _, prov := range provisions { @@ -119,7 +131,14 @@ func signIOS(bi *buildInfo, tmpDir, app string) error { if err != nil { return err } - provAppID, err := runCmd(exec.Command("/usr/libexec/PlistBuddy", "-c", "Print:Entitlements:application-identifier", provInfo)) + + // iOS/macOS Catalyst + provAppIDSearchKey := "Print:Entitlements:application-identifier" + if filepath.Ext(prov) == ".provisionprofile" { + // macOS + provAppIDSearchKey = "Print:Entitlements:com.apple.application-identifier" + } + provAppID, err := runCmd(exec.Command("/usr/libexec/PlistBuddy", "-c", provAppIDSearchKey, provInfo)) if err != nil { return err } @@ -129,7 +148,6 @@ func signIOS(bi *buildInfo, tmpDir, app string) error { continue } // Copy provisioning file. - embedded := filepath.Join(app, "embedded.mobileprovision") if err := copyFile(embedded, prov); err != nil { return err } @@ -149,7 +167,15 @@ func signIOS(bi *buildInfo, tmpDir, app string) error { } identity := sha1.Sum(certDER) idHex := hex.EncodeToString(identity[:]) - _, err = runCmd(exec.Command("codesign", "-s", idHex, "-v", "--entitlements", entFile, app)) + _, err = runCmd(exec.Command( + "codesign", + "--sign", idHex, + "--deep", + "--force", + "--options", "runtime", + "--entitlements", + entFile, + app)) return err } return fmt.Errorf("sign: no valid provisioning profile found for bundle id %q among %v", bi.appID, avail) diff --git a/gogio/macosbuild.go b/gogio/macosbuild.go index 3182059..6a9d124 100644 --- a/gogio/macosbuild.go +++ b/gogio/macosbuild.go @@ -151,7 +151,7 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error { NSHighResolutionCapable CFBundlePackageType - APPL + BNDL {{if .Schemes}} CFBundleURLTypes @@ -237,6 +237,12 @@ func (b *macBuilder) signProgram(buildInfo *buildInfo, binDest string, name stri return err } + // If the key is a provisioning profile use the same signing process as iOS + if strings.HasSuffix(buildInfo.key, ".provisionprofile") { + embedded := filepath.Join(binDest, "Contents", "embedded.provisionprofile") + return signApple(buildInfo, b.TempDir, embedded, binDest) + } + cmd := exec.Command( "codesign", "--deep", diff --git a/gogio/main.go b/gogio/main.go index 3c642e8..e17bc6d 100644 --- a/gogio/main.go +++ b/gogio/main.go @@ -36,7 +36,7 @@ var ( extraLdflags = flag.String("ldflags", "", "extra flags to the Go linker") extraTags = flag.String("tags", "", "extra tags to the Go tool") iconPath = flag.String("icon", "", "specify an icon for iOS and Android") - signKey = flag.String("signkey", "", "specify the path of the keystore to be used to sign Android apk files.") + signKey = flag.String("signkey", "", "specify the path of the keystore to be used to sign Android apk files and macOS app. It can be used for iOS and macOS to specify Provisioning Profiles.") signPass = flag.String("signpass", "", "specify the password to decrypt the signkey.") schemes = flag.String("schemes", "", "specify a list of comma separated deep-linking schemes that the program accepts") notaryID = flag.String("notaryid", "", "specify the apple id to use for notarization.")