From 3235347224d339593666f175b93d8ab370fe467f Mon Sep 17 00:00:00 2001 From: Daniel Wiese Date: Mon, 18 Jan 2021 16:11:06 -0500 Subject: [PATCH 01/24] nominally working example for catalyst --- cmd/gomobile/bind_iosapp.go | 191 ++++++++++++++++++++---------------- cmd/gomobile/env.go | 27 ++++- 2 files changed, 131 insertions(+), 87 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 846a63f49..8a7f20251 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -40,26 +40,24 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { var name string var title string + var buildTemp string + if buildO == "" { name = pkgs[0].Name title = strings.Title(name) - buildO = title + ".framework" + buildO = title + ".xcframework" } else { - if !strings.HasSuffix(buildO, ".framework") { - return fmt.Errorf("static framework name %q missing .framework suffix", buildO) + if !strings.HasSuffix(buildO, ".xcframework") { + return fmt.Errorf("static framework name %q missing .xcframework suffix", buildO) } base := filepath.Base(buildO) - name = base[:len(base)-len(".framework")] + name = base[:len(base)-len(".xcframework")] title = strings.Title(name) } - - fileBases := make([]string, len(pkgs)+1) - for i, pkg := range pkgs { - fileBases[i] = bindPrefix + strings.Title(pkg.Name) + // Build static xcframework output directory. + if err := removeAll(buildO); err != nil { + return err } - fileBases[len(fileBases)-1] = "Universe" - - cmd = exec.Command("xcrun", "lipo", "-create") modulesUsed, err := areGoModulesUsed() if err != nil { @@ -67,6 +65,18 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } for _, arch := range archs { + + // Keep the .framework for each "architecture" to combine into .xcframework + buildTemp = tmpdir + "/" + arch + "/" + title + ".framework" + + fileBases := make([]string, len(pkgs)+1) + for i, pkg := range pkgs { + fileBases[i] = bindPrefix + strings.Title(pkg.Name) + } + fileBases[len(fileBases)-1] = "Universe" + + cmd = exec.Command("xcrun", "lipo", "-create") + if err := writeGoMod("darwin", arch); err != nil { return err } @@ -89,97 +99,108 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return fmt.Errorf("darwin-%s: %v", arch, err) } cmd.Args = append(cmd.Args, "-arch", archClang(arch), path) - } - - // Build static framework output directory. - if err := removeAll(buildO); err != nil { - return err - } - headers := buildO + "/Versions/A/Headers" - if err := mkdir(headers); err != nil { - return err - } - if err := symlink("A", buildO+"/Versions/Current"); err != nil { - return err - } - if err := symlink("Versions/Current/Headers", buildO+"/Headers"); err != nil { - return err - } - if err := symlink("Versions/Current/"+title, buildO+"/"+title); err != nil { - return err - } - cmd.Args = append(cmd.Args, "-o", buildO+"/Versions/A/"+title) - if err := runCmd(cmd); err != nil { - return err - } + headers := buildTemp + "/Versions/A/Headers" + if err := mkdir(headers); err != nil { + return err + } + if err := symlink("A", buildTemp+"/Versions/Current"); err != nil { + return err + } + if err := symlink("Versions/Current/Headers", buildTemp+"/Headers"); err != nil { + return err + } + if err := symlink("Versions/Current/"+title, buildTemp+"/"+title); err != nil { + return err + } - // Copy header file next to output archive. - headerFiles := make([]string, len(fileBases)) - if len(fileBases) == 1 { - headerFiles[0] = title + ".h" - err := copyFile( - headers+"/"+title+".h", - srcDir+"/"+bindPrefix+title+".objc.h", - ) - if err != nil { + cmd.Args = append(cmd.Args, "-o", buildTemp+"/Versions/A/"+title) + if err := runCmd(cmd); err != nil { return err } - } else { - for i, fileBase := range fileBases { - headerFiles[i] = fileBase + ".objc.h" + + // Copy header file next to output archive. + headerFiles := make([]string, len(fileBases)) + if len(fileBases) == 1 { + headerFiles[0] = title + ".h" err := copyFile( - headers+"/"+fileBase+".objc.h", - srcDir+"/"+fileBase+".objc.h") + headers+"/"+title+".h", + srcDir+"/"+bindPrefix+title+".objc.h", + ) + if err != nil { + return err + } + } else { + for i, fileBase := range fileBases { + headerFiles[i] = fileBase + ".objc.h" + err := copyFile( + headers+"/"+fileBase+".objc.h", + srcDir+"/"+fileBase+".objc.h") + if err != nil { + return err + } + } + err := copyFile( + headers+"/ref.h", + srcDir+"/ref.h") + if err != nil { + return err + } + headerFiles = append(headerFiles, title+".h") + err = writeFile(headers+"/"+title+".h", func(w io.Writer) error { + return iosBindHeaderTmpl.Execute(w, map[string]interface{}{ + "pkgs": pkgs, "title": title, "bases": fileBases, + }) + }) if err != nil { return err } } - err := copyFile( - headers+"/ref.h", - srcDir+"/ref.h") - if err != nil { + + resources := buildTemp + "/Versions/A/Resources" + if err := mkdir(resources); err != nil { return err } - headerFiles = append(headerFiles, title+".h") - err = writeFile(headers+"/"+title+".h", func(w io.Writer) error { - return iosBindHeaderTmpl.Execute(w, map[string]interface{}{ - "pkgs": pkgs, "title": title, "bases": fileBases, - }) + if err := symlink("Versions/Current/Resources", buildTemp+"/Resources"); err != nil { + return err + } + err = writeFile(buildTemp+"/Resources/Info.plist", func(w io.Writer) error { + _, err := w.Write([]byte(iosBindInfoPlist)) + return err }) if err != nil { return err } - } - resources := buildO + "/Versions/A/Resources" - if err := mkdir(resources); err != nil { - return err - } - if err := symlink("Versions/Current/Resources", buildO+"/Resources"); err != nil { - return err - } - if err := writeFile(buildO+"/Resources/Info.plist", func(w io.Writer) error { - _, err := w.Write([]byte(iosBindInfoPlist)) - return err - }); err != nil { - return err - } - - var mmVals = struct { - Module string - Headers []string - }{ - Module: title, - Headers: headerFiles, - } - err = writeFile(buildO+"/Versions/A/Modules/module.modulemap", func(w io.Writer) error { - return iosModuleMapTmpl.Execute(w, mmVals) - }) - if err != nil { - return err + var mmVals = struct { + Module string + Headers []string + }{ + Module: title, + Headers: headerFiles, + } + err = writeFile(buildTemp+"/Versions/A/Modules/module.modulemap", func(w io.Writer) error { + return iosModuleMapTmpl.Execute(w, mmVals) + }) + if err != nil { + return err + } + err = symlink("Versions/Current/Modules", buildTemp+"/Modules") + if err != nil { + return err + } + // Thin the arm64 framework with lipo + if arch == "arm64" { + cmd = exec.Command("xcrun", "lipo", buildTemp+"/Versions/A/"+title, "-thin", "arm64", "-output", buildTemp+"/Versions/A/"+title) + if err := runCmd(cmd); err != nil { + return err + } + } } - return symlink("Versions/Current/Modules", buildO+"/Modules") + // Combine frameworks into xcframework + cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/Sample.framework", "-framework", tmpdir+"/amd64/Sample.framework", "-framework", tmpdir+"/catalyst/Sample.framework", "-output", buildO) + err := runCmd(cmd) + return err } const iosBindInfoPlist = ` diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 6dacc630c..1cf981524 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -28,7 +28,7 @@ var ( func allArchs(targetOS string) []string { switch targetOS { case "ios": - return []string{"arm64", "amd64"} + return []string{"arm64", "amd64", "catalyst"} case "android": return []string{"arm", "arm64", "386", "amd64"} default: @@ -152,6 +152,9 @@ func envInit() (err error) { case "amd64": clang, cflags, err = envClang("iphonesimulator") cflags += " -mios-simulator-version-min=" + buildIOSVersion + case "catalyst": + clang, cflags, err = envClang("macosx") + cflags += " -target x86_64-apple-ios13.0-macabi" default: panic(fmt.Errorf("unknown GOARCH: %q", arch)) } @@ -164,13 +167,14 @@ func envInit() (err error) { } env = append(env, "GOOS=darwin", - "GOARCH="+arch, + "GOARCH="+archGo(arch), "CC="+clang, "CXX="+clang+"++", "CGO_CFLAGS="+cflags+" -arch "+archClang(arch), "CGO_CXXFLAGS="+cflags+" -arch "+archClang(arch), "CGO_LDFLAGS="+cflags+" -arch "+archClang(arch), "CGO_ENABLED=1", + "ARCH="+arch, ) darwinEnv[arch] = env } @@ -223,6 +227,23 @@ func envClang(sdkName string) (clang, cflags string, err error) { return clang, "-isysroot " + sdk, nil } +func archGo(goarch string) string { + switch goarch { + case "arm": + return "arm" + case "arm64": + return "arm64" + case "386": + return "386" + case "amd64": + return "amd64" + case "catalyst": + return "amd64" + default: + panic(fmt.Sprintf("unknown GOARCH: %q", goarch)) + } +} + func archClang(goarch string) string { switch goarch { case "arm": @@ -233,6 +254,8 @@ func archClang(goarch string) string { return "i386" case "amd64": return "x86_64" + case "catalyst": + return "x86_64" default: panic(fmt.Sprintf("unknown GOARCH: %q", goarch)) } From e581a493dfdbff795e7e79d6a2a73493fb55325e Mon Sep 17 00:00:00 2001 From: Daniel Wiese Date: Mon, 18 Jan 2021 16:56:38 -0500 Subject: [PATCH 02/24] remove mistaken hardcoded framework filenames --- cmd/gomobile/bind_iosapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 8a7f20251..4da490f59 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -198,7 +198,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } } // Combine frameworks into xcframework - cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/Sample.framework", "-framework", tmpdir+"/amd64/Sample.framework", "-framework", tmpdir+"/catalyst/Sample.framework", "-output", buildO) + cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/" + title + ".framework", "-framework", tmpdir+"/amd64/" + title + ".framework", "-framework", tmpdir+"/catalyst/" + title + ".framework", "-output", buildO) err := runCmd(cmd) return err } From cb8e364336a9a48323105fee8ff669184e0624e6 Mon Sep 17 00:00:00 2001 From: Daniel Wiese Date: Mon, 18 Jan 2021 18:24:44 -0500 Subject: [PATCH 03/24] update test and minor go fmt fix --- cmd/gomobile/bind_iosapp.go | 2 +- cmd/gomobile/bind_test.go | 50 +++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 4da490f59..3da61450a 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -198,7 +198,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } } // Combine frameworks into xcframework - cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/" + title + ".framework", "-framework", tmpdir+"/amd64/" + title + ".framework", "-framework", tmpdir+"/catalyst/" + title + ".framework", "-output", buildO) + cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/"+title+".framework", "-framework", tmpdir+"/amd64/"+title+".framework", "-framework", tmpdir+"/catalyst/"+title+".framework", "-output", buildO) err := runCmd(cmd) return err } diff --git a/cmd/gomobile/bind_test.go b/cmd/gomobile/bind_test.go index 9a5ffa880..aee6587e4 100644 --- a/cmd/gomobile/bind_test.go +++ b/cmd/gomobile/bind_test.go @@ -112,7 +112,7 @@ func TestBindIOS(t *testing.T) { }() buildN = true buildX = true - buildO = "Asset.framework" + buildO = "Asset.xcframework" buildTarget = "ios/arm64" tests := []struct { @@ -126,7 +126,7 @@ func TestBindIOS(t *testing.T) { prefix: "Foo", }, { - out: "Abcde.framework", + out: "Abcde.xcframework", }, } for _, tc := range tests { @@ -160,7 +160,7 @@ func TestBindIOS(t *testing.T) { BitcodeEnabled bool }{ outputData: output, - Output: buildO[:len(buildO)-len(".framework")], + Output: buildO[:len(buildO)-len(".xcframework")], Prefix: tc.prefix, BitcodeEnabled: bitcodeEnabled, } @@ -195,26 +195,28 @@ jar c -C $WORK/javac-output . var bindIOSTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile WORK=$WORK GOOS=darwin CGO_ENABLED=1 gobind -lang=go,objc -outdir=$WORK -tags=ios{{if .Prefix}} -prefix={{.Prefix}}{{end}} golang.org/x/mobile/asset +rm -r -f "{{.Output}}.xcframework" mkdir -p $WORK/src -PWD=$WORK/src GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/{{.Output}}-arm64.a ./gobind -rm -r -f "{{.Output}}.framework" -mkdir -p {{.Output}}.framework/Versions/A/Headers -ln -s A {{.Output}}.framework/Versions/Current -ln -s Versions/Current/Headers {{.Output}}.framework/Headers -ln -s Versions/Current/{{.Output}} {{.Output}}.framework/{{.Output}} -xcrun lipo -create -arch arm64 $WORK/{{.Output}}-arm64.a -o {{.Output}}.framework/Versions/A/{{.Output}} -cp $WORK/src/gobind/{{.Prefix}}Asset.objc.h {{.Output}}.framework/Versions/A/Headers/{{.Prefix}}Asset.objc.h -mkdir -p {{.Output}}.framework/Versions/A/Headers -cp $WORK/src/gobind/Universe.objc.h {{.Output}}.framework/Versions/A/Headers/Universe.objc.h -mkdir -p {{.Output}}.framework/Versions/A/Headers -cp $WORK/src/gobind/ref.h {{.Output}}.framework/Versions/A/Headers/ref.h -mkdir -p {{.Output}}.framework/Versions/A/Headers -mkdir -p {{.Output}}.framework/Versions/A/Headers -mkdir -p {{.Output}}.framework/Versions/A/Resources -ln -s Versions/Current/Resources {{.Output}}.framework/Resources -mkdir -p {{.Output}}.framework/Resources -mkdir -p {{.Output}}.framework/Versions/A/Modules -ln -s Versions/Current/Modules {{.Output}}.framework/Modules +PWD=$WORK/src GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 ARCH=arm64 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/{{.Output}}-arm64.a ./gobind +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers +ln -s A $WORK/arm64/{{.Output}}.framework/Versions/Current +ln -s Versions/Current/Headers $WORK/arm64/{{.Output}}.framework/Headers +ln -s Versions/Current/{{.Output}} $WORK/arm64/{{.Output}}.framework/{{.Output}} +xcrun lipo -create -arch arm64 $WORK/{{.Output}}-arm64.a -o $WORK/arm64/{{.Output}}.framework/Versions/A/{{.Output}} +cp $WORK/src/gobind/{{.Prefix}}Asset.objc.h $WORK/arm64/{{.Output}}.framework/Versions/A/Headers/{{.Prefix}}Asset.objc.h +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers +cp $WORK/src/gobind/Universe.objc.h $WORK/arm64/{{.Output}}.framework/Versions/A/Headers/Universe.objc.h +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers +cp $WORK/src/gobind/ref.h $WORK/arm64/{{.Output}}.framework/Versions/A/Headers/ref.h +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Resources +ln -s Versions/Current/Resources $WORK/arm64/{{.Output}}.framework/Resources +mkdir -p $WORK/arm64/{{.Output}}.framework/Resources +mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Modules +ln -s Versions/Current/Modules $WORK/arm64/{{.Output}}.framework/Modules +xcrun lipo $WORK/arm64/{{.Output}}.framework/Versions/A/{{.Output}} -thin arm64 -output $WORK/arm64/{{.Output}}.framework/Versions/A/{{.Output}} +xcodebuild -create-xcframework -framework $WORK/arm64/{{.Output}}.framework -framework $WORK/amd64/{{.Output}}.framework -framework $WORK/catalyst/{{.Output}}.framework -output {{.Output}}.xcframework `)) func TestBindIOSAll(t *testing.T) { @@ -231,7 +233,7 @@ func TestBindIOSAll(t *testing.T) { }() buildN = true buildX = true - buildO = "Asset.framework" + buildO = "Asset.xcframework" buildTarget = "ios" buf := new(bytes.Buffer) @@ -291,7 +293,7 @@ func TestBindWithGoModules(t *testing.T) { case "android": out = filepath.Join(dir, "cgopkg.aar") case "ios": - out = filepath.Join(dir, "Cgopkg.framework") + out = filepath.Join(dir, "Cgopkg.xcframework") } tests := []struct { From eb6b77b0e65be3c33673692d4ab94e90c327c5e7 Mon Sep 17 00:00:00 2001 From: Baye Date: Fri, 29 Jan 2021 16:01:59 +0800 Subject: [PATCH 04/24] Support Apple Silicon and Catalyst create one framework for all targets: ios, simulator and catalyst, every framework contains at least one arch library, and combine all framework into one xcframework --- cmd/gomobile/bind_iosapp.go | 235 ++++++++++++++++++++---------------- cmd/gomobile/build.go | 1 + cmd/gomobile/env.go | 117 ++++++++++-------- go.sum | 1 + 4 files changed, 195 insertions(+), 159 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 3da61450a..76f0021ea 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -64,142 +64,165 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return err } - for _, arch := range archs { + targets := allTargets("ios") - // Keep the .framework for each "architecture" to combine into .xcframework - buildTemp = tmpdir + "/" + arch + "/" + title + ".framework" + // create separate framework for ios,simulator and catalyst + // every target has at least one arch (arm64 and x86_64) + for _, target := range targets { + archs := allTargetArchs("ios", target) - fileBases := make([]string, len(pkgs)+1) - for i, pkg := range pkgs { - fileBases[i] = bindPrefix + strings.Title(pkg.Name) - } - fileBases[len(fileBases)-1] = "Universe" + for index, arch := range archs { + buildTemp = tmpdir + "/" + target + "/" + title + ".framework" - cmd = exec.Command("xcrun", "lipo", "-create") + fileBases := make([]string, len(pkgs)+1) + for i, pkg := range pkgs { + fileBases[i] = bindPrefix + strings.Title(pkg.Name) + } + fileBases[len(fileBases)-1] = "Universe" - if err := writeGoMod("darwin", arch); err != nil { - return err - } + cmd = exec.Command("xcrun", "lipo", "-create") - env := darwinEnv[arch] - // Add the generated packages to GOPATH for reverse bindings. - gopath := fmt.Sprintf("GOPATH=%s%c%s", tmpdir, filepath.ListSeparator, goEnv("GOPATH")) - env = append(env, gopath) + env := darwinEnv[target+"_"+arch] - // Run `go mod tidy` to force to create go.sum. - // Without go.sum, `go build` fails as of Go 1.16. - if modulesUsed { - if err := goModTidyAt(filepath.Join(tmpdir, "src"), env); err != nil { + if err := writeGoMod("darwin", getenv(env, "GOARCH")); err != nil { return err } - } - path, err := goIOSBindArchive(name, env, filepath.Join(tmpdir, "src")) - if err != nil { - return fmt.Errorf("darwin-%s: %v", arch, err) - } - cmd.Args = append(cmd.Args, "-arch", archClang(arch), path) + // Add the generated packages to GOPATH for reverse bindings. + gopath := fmt.Sprintf("GOPATH=%s%c%s", tmpdir, filepath.ListSeparator, goEnv("GOPATH")) + env = append(env, gopath) + fmt.Printf("[debug] goenv:\n%s\n", env) - headers := buildTemp + "/Versions/A/Headers" - if err := mkdir(headers); err != nil { - return err - } - if err := symlink("A", buildTemp+"/Versions/Current"); err != nil { - return err - } - if err := symlink("Versions/Current/Headers", buildTemp+"/Headers"); err != nil { - return err - } - if err := symlink("Versions/Current/"+title, buildTemp+"/"+title); err != nil { - return err - } - - cmd.Args = append(cmd.Args, "-o", buildTemp+"/Versions/A/"+title) - if err := runCmd(cmd); err != nil { - return err - } + // Run `go mod tidy` to force to create go.sum. + // Without go.sum, `go build` fails as of Go 1.16. + if modulesUsed { + if err := goModTidyAt(filepath.Join(tmpdir, "src"), env); err != nil { + return err + } + } - // Copy header file next to output archive. - headerFiles := make([]string, len(fileBases)) - if len(fileBases) == 1 { - headerFiles[0] = title + ".h" - err := copyFile( - headers+"/"+title+".h", - srcDir+"/"+bindPrefix+title+".objc.h", - ) + path, err := goIOSBindArchive(name, env, filepath.Join(tmpdir, "src")) if err != nil { + return fmt.Errorf("darwin-%s: %v", arch, err) + } + + if index > 0 { + // not the first static lib, attach to a fat library and skip create headers + fatCmd := exec.Command("xcrun", "lipo", "-create", + "-output", buildTemp+"/Versions/A/"+title, + buildTemp+"/Versions/A/"+title, path) + + if err := runCmd(fatCmd); err != nil { + return err + } + + continue + } + + cmd.Args = append(cmd.Args, "-arch", archClang(arch), path) + + headers := buildTemp + "/Versions/A/Headers" + if err := mkdir(headers); err != nil { + return err + } + if err := symlink("A", buildTemp+"/Versions/Current"); err != nil { return err } - } else { - for i, fileBase := range fileBases { - headerFiles[i] = fileBase + ".objc.h" + if err := symlink("Versions/Current/Headers", buildTemp+"/Headers"); err != nil { + return err + } + if err := symlink("Versions/Current/"+title, buildTemp+"/"+title); err != nil { + return err + } + + cmd.Args = append(cmd.Args, "-o", buildTemp+"/Versions/A/"+title) + if err := runCmd(cmd); err != nil { + return err + } + + //Copy header file next to output archive. + headerFiles := make([]string, len(fileBases)) + if len(fileBases) == 1 { + headerFiles[0] = title + ".h" err := copyFile( - headers+"/"+fileBase+".objc.h", - srcDir+"/"+fileBase+".objc.h") + headers+"/"+title+".h", + srcDir+"/"+bindPrefix+title+".objc.h", + ) + if err != nil { + return err + } + } else { + for i, fileBase := range fileBases { + headerFiles[i] = fileBase + ".objc.h" + err := copyFile( + headers+"/"+fileBase+".objc.h", + srcDir+"/"+fileBase+".objc.h") + if err != nil { + return err + } + } + err := copyFile( + headers+"/ref.h", + srcDir+"/ref.h") + if err != nil { + return err + } + headerFiles = append(headerFiles, title+".h") + err = writeFile(headers+"/"+title+".h", func(w io.Writer) error { + return iosBindHeaderTmpl.Execute(w, map[string]interface{}{ + "pkgs": pkgs, "title": title, "bases": fileBases, + }) + }) if err != nil { return err } } - err := copyFile( - headers+"/ref.h", - srcDir+"/ref.h") - if err != nil { + + resources := buildTemp + "/Versions/A/Resources" + if err := mkdir(resources); err != nil { return err } - headerFiles = append(headerFiles, title+".h") - err = writeFile(headers+"/"+title+".h", func(w io.Writer) error { - return iosBindHeaderTmpl.Execute(w, map[string]interface{}{ - "pkgs": pkgs, "title": title, "bases": fileBases, - }) + if err := symlink("Versions/Current/Resources", buildTemp+"/Resources"); err != nil { + return err + } + err = writeFile(buildTemp+"/Resources/Info.plist", func(w io.Writer) error { + _, err := w.Write([]byte(iosBindInfoPlist)) + return err }) if err != nil { return err } - } - - resources := buildTemp + "/Versions/A/Resources" - if err := mkdir(resources); err != nil { - return err - } - if err := symlink("Versions/Current/Resources", buildTemp+"/Resources"); err != nil { - return err - } - err = writeFile(buildTemp+"/Resources/Info.plist", func(w io.Writer) error { - _, err := w.Write([]byte(iosBindInfoPlist)) - return err - }) - if err != nil { - return err - } - var mmVals = struct { - Module string - Headers []string - }{ - Module: title, - Headers: headerFiles, - } - err = writeFile(buildTemp+"/Versions/A/Modules/module.modulemap", func(w io.Writer) error { - return iosModuleMapTmpl.Execute(w, mmVals) - }) - if err != nil { - return err - } - err = symlink("Versions/Current/Modules", buildTemp+"/Modules") - if err != nil { - return err - } - // Thin the arm64 framework with lipo - if arch == "arm64" { - cmd = exec.Command("xcrun", "lipo", buildTemp+"/Versions/A/"+title, "-thin", "arm64", "-output", buildTemp+"/Versions/A/"+title) - if err := runCmd(cmd); err != nil { + var mmVals = struct { + Module string + Headers []string + }{ + Module: title, + Headers: headerFiles, + } + err = writeFile(buildTemp+"/Versions/A/Modules/module.modulemap", func(w io.Writer) error { + return iosModuleMapTmpl.Execute(w, mmVals) + }) + if err != nil { + return err + } + err = symlink("Versions/Current/Modules", buildTemp+"/Modules") + if err != nil { return err } } } - // Combine frameworks into xcframework - cmd = exec.Command("xcodebuild", "-create-xcframework", "-framework", tmpdir+"/arm64/"+title+".framework", "-framework", tmpdir+"/amd64/"+title+".framework", "-framework", tmpdir+"/catalyst/"+title+".framework", "-output", buildO) - err := runCmd(cmd) + + // Finally combine ios/simulator/catalyst framework to xcframework + xcframeworkArgs := []string{"-create-xcframework"} + + for _, target := range allTargets("ios") { + xcframeworkArgs = append(xcframeworkArgs, "-framework", tmpdir+"/"+target+"/"+title+".framework") + } + + xcframeworkArgs = append(xcframeworkArgs, "-output", buildO) + cmd = exec.Command("xcodebuild", xcframeworkArgs...) + err = runCmd(cmd) return err } diff --git a/cmd/gomobile/build.go b/cmd/gomobile/build.go index 072af001f..df81e73a3 100644 --- a/cmd/gomobile/build.go +++ b/cmd/gomobile/build.go @@ -290,6 +290,7 @@ func goCmd(subcmd string, srcs []string, env []string, args ...string) error { func goCmdAt(at string, subcmd string, srcs []string, env []string, args ...string) error { cmd := exec.Command("go", subcmd) + //cmd := exec.Command("go1.16rc1", subcmd) tags := buildTags targetOS, _, err := parseBuildTarget(buildTarget) if err != nil { diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 1cf981524..fbf47cde4 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -36,6 +36,33 @@ func allArchs(targetOS string) []string { } } +func allTargets(targetOS string) []string { + switch targetOS { + case "ios": + return []string{"simulator", "ios", "catalyst"} + default: + panic(fmt.Sprintf("unexpected target OS: %s", targetOS)) + } +} + +func allTargetArchs(targetOS string, target string) []string { + switch targetOS { + case "ios": + switch target { + case "simulator": + return []string{"arm64", "amd64"} + case "ios": + return []string{"arm64"} + case "catalyst": + return []string{"arm64", "amd64"} + default: + panic(fmt.Sprintf("unexpected ios target: %s", target)) + } + default: + panic(fmt.Sprintf("unexpected target OS: %s", targetOS)) + } +} + func buildEnvInit() (cleanup func(), err error) { // Find gomobilepath. gopath := goEnv("GOPATH") @@ -141,42 +168,45 @@ func envInit() (err error) { darwinArmNM = "nm" darwinEnv = make(map[string][]string) - for _, arch := range allArchs("ios") { - var env []string - var err error - var clang, cflags string - switch arch { - case "arm64": - clang, cflags, err = envClang("iphoneos") - cflags += " -miphoneos-version-min=" + buildIOSVersion - case "amd64": - clang, cflags, err = envClang("iphonesimulator") - cflags += " -mios-simulator-version-min=" + buildIOSVersion - case "catalyst": - clang, cflags, err = envClang("macosx") - cflags += " -target x86_64-apple-ios13.0-macabi" - default: - panic(fmt.Errorf("unknown GOARCH: %q", arch)) - } - if err != nil { - return err - } + for _, target := range allTargets("ios") { + for _, arch := range allTargetArchs("ios", target) { + var env []string + var err error + var clang, cflags string + switch target { + case "ios": + clang, cflags, err = envClang("iphoneos") + cflags += " -miphoneos-version-min=" + buildIOSVersion + case "simulator": + clang, cflags, err = envClang("iphonesimulator") + cflags += " -mios-simulator-version-min=" + buildIOSVersion + case "catalyst": + clang, cflags, err = envClang("macosx") + cflags += " -target x86_64-apple-ios13.0-macabi" + default: + panic(fmt.Errorf("unknown ios target: %q", arch)) + } + + if err != nil { + return err + } - if bitcodeEnabled { - cflags += " -fembed-bitcode" + if bitcodeEnabled { + cflags += " -fembed-bitcode" + } + env = append(env, + "GOOS=darwin", + "GOARCH="+arch, + "CC="+clang, + "CXX="+clang+"++", + "CGO_CFLAGS="+cflags+" -arch "+archClang(arch), + "CGO_CXXFLAGS="+cflags+" -arch "+archClang(arch), + "CGO_LDFLAGS="+cflags+" -arch "+archClang(arch), + "CGO_ENABLED=1", + "ARCH="+arch, + ) + darwinEnv[target + "_" + arch] = env } - env = append(env, - "GOOS=darwin", - "GOARCH="+archGo(arch), - "CC="+clang, - "CXX="+clang+"++", - "CGO_CFLAGS="+cflags+" -arch "+archClang(arch), - "CGO_CXXFLAGS="+cflags+" -arch "+archClang(arch), - "CGO_LDFLAGS="+cflags+" -arch "+archClang(arch), - "CGO_ENABLED=1", - "ARCH="+arch, - ) - darwinEnv[arch] = env } return nil @@ -227,23 +257,6 @@ func envClang(sdkName string) (clang, cflags string, err error) { return clang, "-isysroot " + sdk, nil } -func archGo(goarch string) string { - switch goarch { - case "arm": - return "arm" - case "arm64": - return "arm64" - case "386": - return "386" - case "amd64": - return "amd64" - case "catalyst": - return "amd64" - default: - panic(fmt.Sprintf("unknown GOARCH: %q", goarch)) - } -} - func archClang(goarch string) string { switch goarch { case "arm": @@ -254,8 +267,6 @@ func archClang(goarch string) string { return "i386" case "amd64": return "x86_64" - case "catalyst": - return "x86_64" default: panic(fmt.Sprintf("unknown GOARCH: %q", goarch)) } diff --git a/go.sum b/go.sum index 79a6d20d1..536cecdfd 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= From 259d8613918a05553df07f8d6aa425cf46642027 Mon Sep 17 00:00:00 2001 From: Baye Date: Wed, 3 Feb 2021 11:16:46 +0800 Subject: [PATCH 05/24] remove catalyst in allArchs --- cmd/gomobile/env.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index fbf47cde4..88520c9a0 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -28,7 +28,7 @@ var ( func allArchs(targetOS string) []string { switch targetOS { case "ios": - return []string{"arm64", "amd64", "catalyst"} + return []string{"arm64", "amd64"} case "android": return []string{"arm", "arm64", "386", "amd64"} default: From b678ba0b8987240d748db5b25e5c4d9b9e4d8670 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Mon, 1 Mar 2021 12:11:47 -0800 Subject: [PATCH 06/24] cmd/gomobile: macOS support Adds macosx on amd64 and arm64 targets to the fat xcframework. This enables the generated xcframework to be used as a binary dependency in Swift Package Manager: https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages and used or tested using the SwiftPM command-line tools on macOS, e.g. 'swift test' --- cmd/gomobile/env.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 88520c9a0..db47defd7 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -39,7 +39,7 @@ func allArchs(targetOS string) []string { func allTargets(targetOS string) []string { switch targetOS { case "ios": - return []string{"simulator", "ios", "catalyst"} + return []string{"simulator", "ios", "catalyst", "macosx"} default: panic(fmt.Sprintf("unexpected target OS: %s", targetOS)) } @@ -55,6 +55,8 @@ func allTargetArchs(targetOS string, target string) []string { return []string{"arm64"} case "catalyst": return []string{"arm64", "amd64"} + case "macosx": + return []string{"arm64", "amd64"} default: panic(fmt.Sprintf("unexpected ios target: %s", target)) } @@ -183,6 +185,9 @@ func envInit() (err error) { case "catalyst": clang, cflags, err = envClang("macosx") cflags += " -target x86_64-apple-ios13.0-macabi" + case "macosx": + clang, cflags, err = envClang("macosx") + // cflags += " -target x86_64-apple-ios13.0-macabi" default: panic(fmt.Errorf("unknown ios target: %q", arch)) } @@ -205,7 +210,7 @@ func envInit() (err error) { "CGO_ENABLED=1", "ARCH="+arch, ) - darwinEnv[target + "_" + arch] = env + darwinEnv[target+"_"+arch] = env } } From df9f79bb1c1759d3a0dc8b181f1b46aee80b9b7f Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 10:19:46 -0700 Subject: [PATCH 07/24] cmd/gomobile: use correct MacCatalyst ABI for arm64 --- cmd/gomobile/env.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index db47defd7..067518c48 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -184,7 +184,12 @@ func envInit() (err error) { cflags += " -mios-simulator-version-min=" + buildIOSVersion case "catalyst": clang, cflags, err = envClang("macosx") - cflags += " -target x86_64-apple-ios13.0-macabi" + switch arch { + case "amd64": + cflags += " -target x86_64-apple-ios13.0-macabi" + case "arm64": + cflags += " -target arm64-apple-ios13.0-macabi" + } case "macosx": clang, cflags, err = envClang("macosx") // cflags += " -target x86_64-apple-ios13.0-macabi" From 9d627d1b88ec1fa953810f2bed4a1fbb81c3d88f Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 11:04:48 -0700 Subject: [PATCH 08/24] cmd/gomobile: remove commented-out go1.16rc1 exec --- cmd/gomobile/build.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/gomobile/build.go b/cmd/gomobile/build.go index df81e73a3..072af001f 100644 --- a/cmd/gomobile/build.go +++ b/cmd/gomobile/build.go @@ -290,7 +290,6 @@ func goCmd(subcmd string, srcs []string, env []string, args ...string) error { func goCmdAt(at string, subcmd string, srcs []string, env []string, args ...string) error { cmd := exec.Command("go", subcmd) - //cmd := exec.Command("go1.16rc1", subcmd) tags := buildTags targetOS, _, err := parseBuildTarget(buildTarget) if err != nil { From 9a25750d5e62352de7e259b8d7fb379cdd6fbf18 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 11:13:50 -0700 Subject: [PATCH 09/24] cmd/gomobile: address CL feedback; remove commented-out line --- cmd/gomobile/env.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 067518c48..44eb24899 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -192,7 +192,6 @@ func envInit() (err error) { } case "macosx": clang, cflags, err = envClang("macosx") - // cflags += " -target x86_64-apple-ios13.0-macabi" default: panic(fmt.Errorf("unknown ios target: %q", arch)) } From 7db0e8867fd1885381d89869d0d00df0ed901efd Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 11:15:11 -0700 Subject: [PATCH 10/24] cmd/gomobile: remove debugging line per CL feedback --- cmd/gomobile/bind_iosapp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 76f0021ea..2c7e0a59b 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -91,7 +91,6 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { // Add the generated packages to GOPATH for reverse bindings. gopath := fmt.Sprintf("GOPATH=%s%c%s", tmpdir, filepath.ListSeparator, goEnv("GOPATH")) env = append(env, gopath) - fmt.Printf("[debug] goenv:\n%s\n", env) // Run `go mod tidy` to force to create go.sum. // Without go.sum, `go build` fails as of Go 1.16. From abb78bd28e5e3f3459a2f30fa660e69868c90293 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 11:16:58 -0700 Subject: [PATCH 11/24] cmd/gomobile: remove single-use 'targets' variable --- cmd/gomobile/bind_iosapp.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 2c7e0a59b..e0842f627 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -64,11 +64,9 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return err } - targets := allTargets("ios") - // create separate framework for ios,simulator and catalyst // every target has at least one arch (arm64 and x86_64) - for _, target := range targets { + for _, target := range allTargets("ios") { archs := allTargetArchs("ios", target) for index, arch := range archs { From e8912815fbcb3818e32258c92edcba910f5608b9 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 19:26:48 -0700 Subject: [PATCH 12/24] cmd/gomobile: rename allTargetArchs to iOSTargetArchs CL feedback --- cmd/gomobile/bind_iosapp.go | 4 +--- cmd/gomobile/env.go | 27 +++++++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index e0842f627..311c02e2c 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -67,9 +67,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { // create separate framework for ios,simulator and catalyst // every target has at least one arch (arm64 and x86_64) for _, target := range allTargets("ios") { - archs := allTargetArchs("ios", target) - - for index, arch := range archs { + for index, arch := range iOSTargetArchs(target) { buildTemp = tmpdir + "/" + target + "/" + title + ".framework" fileBases := make([]string, len(pkgs)+1) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 44eb24899..dcd7e96f8 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -45,23 +45,18 @@ func allTargets(targetOS string) []string { } } -func allTargetArchs(targetOS string, target string) []string { - switch targetOS { +func iOSTargetArchs(target string) []string { + switch target { + case "simulator": + return []string{"arm64", "amd64"} case "ios": - switch target { - case "simulator": - return []string{"arm64", "amd64"} - case "ios": - return []string{"arm64"} - case "catalyst": - return []string{"arm64", "amd64"} - case "macosx": - return []string{"arm64", "amd64"} - default: - panic(fmt.Sprintf("unexpected ios target: %s", target)) - } + return []string{"arm64"} + case "catalyst": + return []string{"arm64", "amd64"} + case "macosx": + return []string{"arm64", "amd64"} default: - panic(fmt.Sprintf("unexpected target OS: %s", targetOS)) + panic(fmt.Sprintf("unexpected iOS target: %s", target)) } } @@ -171,7 +166,7 @@ func envInit() (err error) { darwinArmNM = "nm" darwinEnv = make(map[string][]string) for _, target := range allTargets("ios") { - for _, arch := range allTargetArchs("ios", target) { + for _, arch := range iOSTargetArchs(target) { var env []string var err error var clang, cflags string From 9d00df1fb790d2b6c1e324be3d9c19ef41e96c87 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 19:29:13 -0700 Subject: [PATCH 13/24] cmd/gomobile: replace allTargets with iOSTargets slice --- cmd/gomobile/bind_iosapp.go | 4 ++-- cmd/gomobile/env.go | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 311c02e2c..ca717aaca 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -66,7 +66,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { // create separate framework for ios,simulator and catalyst // every target has at least one arch (arm64 and x86_64) - for _, target := range allTargets("ios") { + for _, target := range iOSTargets { for index, arch := range iOSTargetArchs(target) { buildTemp = tmpdir + "/" + target + "/" + title + ".framework" @@ -211,7 +211,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { // Finally combine ios/simulator/catalyst framework to xcframework xcframeworkArgs := []string{"-create-xcframework"} - for _, target := range allTargets("ios") { + for _, target := range iOSTargets { xcframeworkArgs = append(xcframeworkArgs, "-framework", tmpdir+"/"+target+"/"+title+".framework") } diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index dcd7e96f8..b2a98a072 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -36,14 +36,7 @@ func allArchs(targetOS string) []string { } } -func allTargets(targetOS string) []string { - switch targetOS { - case "ios": - return []string{"simulator", "ios", "catalyst", "macosx"} - default: - panic(fmt.Sprintf("unexpected target OS: %s", targetOS)) - } -} +var iOSTargets = []string{"simulator", "ios", "catalyst", "macosx"} func iOSTargetArchs(target string) []string { switch target { @@ -165,7 +158,7 @@ func envInit() (err error) { darwinArmNM = "nm" darwinEnv = make(map[string][]string) - for _, target := range allTargets("ios") { + for _, target := range iOSTargets { for _, arch := range iOSTargetArchs(target) { var env []string var err error From cdc07c0698e4e4c76409efb0c66a3a6f2856f394 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 19:31:46 -0700 Subject: [PATCH 14/24] =?UTF-8?q?cmd/gomobile:=20macosx=20=E2=86=92=20maco?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CL feedback --- cmd/gomobile/env.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index b2a98a072..0c7484243 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -36,7 +36,7 @@ func allArchs(targetOS string) []string { } } -var iOSTargets = []string{"simulator", "ios", "catalyst", "macosx"} +var iOSTargets = []string{"simulator", "ios", "catalyst", "macos"} func iOSTargetArchs(target string) []string { switch target { @@ -46,7 +46,7 @@ func iOSTargetArchs(target string) []string { return []string{"arm64"} case "catalyst": return []string{"arm64", "amd64"} - case "macosx": + case "macos": return []string{"arm64", "amd64"} default: panic(fmt.Sprintf("unexpected iOS target: %s", target)) @@ -178,7 +178,8 @@ func envInit() (err error) { case "arm64": cflags += " -target arm64-apple-ios13.0-macabi" } - case "macosx": + case "macos": + // Note: the SDK is called "macosx", not "macos" clang, cflags, err = envClang("macosx") default: panic(fmt.Errorf("unknown ios target: %q", arch)) From ab263e4123aad50e0c80148fb8ce944c1b0e2d67 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 19:34:52 -0700 Subject: [PATCH 15/24] cmd/gomobile: add comment describing iOSTargets var --- cmd/gomobile/env.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 0c7484243..029d00a6f 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -36,6 +36,9 @@ func allArchs(targetOS string) []string { } } +// gomobile's "ios" target OS actually builds for multiple Apple platforms: +// iOS, iPadOS, MacCatalyst (iOS on macOS), and macOS. +// TODO: support watchOS and tvOS? var iOSTargets = []string{"simulator", "ios", "catalyst", "macos"} func iOSTargetArchs(target string) []string { From 50f941d1f5dd056d4e435b62ef67368908905af9 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 8 Jul 2021 21:45:46 -0700 Subject: [PATCH 16/24] cmd/gomobile: update iOSTargets comment per CL feedback --- cmd/gomobile/env.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 029d00a6f..8a12589c4 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -36,7 +36,8 @@ func allArchs(targetOS string) []string { } } -// gomobile's "ios" target OS actually builds for multiple Apple platforms: +// iOSTargets lists Apple platforms as individual sub-targets. +// The gomobile "ios" target actually builds for multiple Apple platforms: // iOS, iPadOS, MacCatalyst (iOS on macOS), and macOS. // TODO: support watchOS and tvOS? var iOSTargets = []string{"simulator", "ios", "catalyst", "macos"} From 8a0a1e6ad613297c6e423595e5df28ac1b7eb002 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 09:37:48 -0700 Subject: [PATCH 17/24] cmd/gomobile: remove unnecessary ARCH env var --- cmd/gomobile/env.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index 8a12589c4..b342f3e86 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -205,7 +205,6 @@ func envInit() (err error) { "CGO_CXXFLAGS="+cflags+" -arch "+archClang(arch), "CGO_LDFLAGS="+cflags+" -arch "+archClang(arch), "CGO_ENABLED=1", - "ARCH="+arch, ) darwinEnv[target+"_"+arch] = env } From 221210c78f088335396b64c194c1334ae97ca56c Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 09:49:50 -0700 Subject: [PATCH 18/24] cmd/gomobile: remove ARCH=arm64 from test --- cmd/gomobile/bind_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gomobile/bind_test.go b/cmd/gomobile/bind_test.go index aee6587e4..fed814291 100644 --- a/cmd/gomobile/bind_test.go +++ b/cmd/gomobile/bind_test.go @@ -197,7 +197,7 @@ WORK=$WORK GOOS=darwin CGO_ENABLED=1 gobind -lang=go,objc -outdir=$WORK -tags=ios{{if .Prefix}} -prefix={{.Prefix}}{{end}} golang.org/x/mobile/asset rm -r -f "{{.Output}}.xcframework" mkdir -p $WORK/src -PWD=$WORK/src GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 ARCH=arm64 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/{{.Output}}-arm64.a ./gobind +PWD=$WORK/src GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/{{.Output}}-arm64.a ./gobind mkdir -p $WORK/arm64/{{.Output}}.framework/Versions/A/Headers ln -s A $WORK/arm64/{{.Output}}.framework/Versions/Current ln -s Versions/Current/Headers $WORK/arm64/{{.Output}}.framework/Headers From 45defed548c3bf549cc57c51728a8818ebbcf49d Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:02:52 -0700 Subject: [PATCH 19/24] cmd/gomobile: remove comment per CL feedback --- cmd/gomobile/bind_iosapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index ca717aaca..8b9ff7e29 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -54,7 +54,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { name = base[:len(base)-len(".xcframework")] title = strings.Title(name) } - // Build static xcframework output directory. + if err := removeAll(buildO); err != nil { return err } From cb1feedea8604f5a4c4b261ad2d802c3c6e56835 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:32:44 -0700 Subject: [PATCH 20/24] cmd/gomobile: add space after // (CL feedback) --- cmd/gomobile/bind_iosapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 8b9ff7e29..460d09542 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -135,7 +135,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return err } - //Copy header file next to output archive. + // Copy header file next to output archive. headerFiles := make([]string, len(fileBases)) if len(fileBases) == 1 { headerFiles[0] = title + ".h" From 6fd5aa785a2c2af9e2c5e59e3aec50142eea2c56 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:37:24 -0700 Subject: [PATCH 21/24] cmd/gomobile: reorganize variables; use filepath.Join ...instead of string concatenation. CL feedback. --- cmd/gomobile/bind_iosapp.go | 76 ++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 460d09542..ba58a0130 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -40,7 +40,6 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { var name string var title string - var buildTemp string if buildO == "" { name = pkgs[0].Name @@ -66,18 +65,18 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { // create separate framework for ios,simulator and catalyst // every target has at least one arch (arm64 and x86_64) + var frameworkDirs []string for _, target := range iOSTargets { - for index, arch := range iOSTargetArchs(target) { - buildTemp = tmpdir + "/" + target + "/" + title + ".framework" + frameworkDir := filepath.Join(tmpdir, target, title+".framework") + frameworkDirs = append(frameworkDirs, frameworkDir) + for index, arch := range iOSTargetArchs(target) { fileBases := make([]string, len(pkgs)+1) for i, pkg := range pkgs { fileBases[i] = bindPrefix + strings.Title(pkg.Name) } fileBases[len(fileBases)-1] = "Universe" - cmd = exec.Command("xcrun", "lipo", "-create") - env := darwinEnv[target+"_"+arch] if err := writeGoMod("darwin", getenv(env, "GOARCH")); err != nil { @@ -101,37 +100,41 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return fmt.Errorf("darwin-%s: %v", arch, err) } + versionsDir := filepath.Join(frameworkDir, "Versions") + versionsADir := filepath.Join(versionsDir, "A") + titlePath := filepath.Join(versionsADir, title) if index > 0 { // not the first static lib, attach to a fat library and skip create headers - fatCmd := exec.Command("xcrun", "lipo", "-create", - "-output", buildTemp+"/Versions/A/"+title, - buildTemp+"/Versions/A/"+title, path) - + fatCmd := exec.Command( + "xcrun", + "lipo", "-create", "-output", titlePath, titlePath, path, + ) if err := runCmd(fatCmd); err != nil { return err } - continue } - cmd.Args = append(cmd.Args, "-arch", archClang(arch), path) - - headers := buildTemp + "/Versions/A/Headers" - if err := mkdir(headers); err != nil { + versionsAHeadersDir := filepath.Join(versionsADir, "Headers") + if err := mkdir(versionsAHeadersDir); err != nil { return err } - if err := symlink("A", buildTemp+"/Versions/Current"); err != nil { + versionsCurrentDir := filepath.Join(versionsDir, "Current") + if err := symlink("A", versionsCurrentDir); err != nil { return err } - if err := symlink("Versions/Current/Headers", buildTemp+"/Headers"); err != nil { + if err := symlink("Versions/Current/Headers", filepath.Join(frameworkDir, "Headers")); err != nil { return err } - if err := symlink("Versions/Current/"+title, buildTemp+"/"+title); err != nil { + if err := symlink(filepath.Join("Versions/Current", title), filepath.Join(frameworkDir, title)); err != nil { return err } - cmd.Args = append(cmd.Args, "-o", buildTemp+"/Versions/A/"+title) - if err := runCmd(cmd); err != nil { + lipoCmd := exec.Command( + "xcrun", + "lipo", "-create", "-arch", archClang(arch), path, "-o", titlePath, + ) + if err := runCmd(lipoCmd); err != nil { return err } @@ -140,8 +143,8 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { if len(fileBases) == 1 { headerFiles[0] = title + ".h" err := copyFile( - headers+"/"+title+".h", - srcDir+"/"+bindPrefix+title+".objc.h", + filepath.Join(versionsAHeadersDir, title+".h"), + filepath.Join(srcDir, bindPrefix+title+".objc.h"), ) if err != nil { return err @@ -150,20 +153,22 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { for i, fileBase := range fileBases { headerFiles[i] = fileBase + ".objc.h" err := copyFile( - headers+"/"+fileBase+".objc.h", - srcDir+"/"+fileBase+".objc.h") + filepath.Join(versionsAHeadersDir, fileBase+".objc.h"), + filepath.Join(srcDir, fileBase+".objc.h"), + ) if err != nil { return err } } err := copyFile( - headers+"/ref.h", - srcDir+"/ref.h") + filepath.Join(versionsAHeadersDir, "ref.h"), + filepath.Join(srcDir, "ref.h"), + ) if err != nil { return err } headerFiles = append(headerFiles, title+".h") - err = writeFile(headers+"/"+title+".h", func(w io.Writer) error { + err = writeFile(filepath.Join(versionsAHeadersDir, title+".h"), func(w io.Writer) error { return iosBindHeaderTmpl.Execute(w, map[string]interface{}{ "pkgs": pkgs, "title": title, "bases": fileBases, }) @@ -173,14 +178,15 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } } - resources := buildTemp + "/Versions/A/Resources" - if err := mkdir(resources); err != nil { + resourcesADir := filepath.Join(versionsADir, "Resources") + resourcesDir := filepath.Join(frameworkDir, "Resources") + if err := mkdir(resourcesADir); err != nil { return err } - if err := symlink("Versions/Current/Resources", buildTemp+"/Resources"); err != nil { + if err := symlink("Versions/Current/Resources", filepath.Join(frameworkDir, "Resources")); err != nil { return err } - err = writeFile(buildTemp+"/Resources/Info.plist", func(w io.Writer) error { + err = writeFile(filepath.Join(resourcesDir, "Info.plist"), func(w io.Writer) error { _, err := w.Write([]byte(iosBindInfoPlist)) return err }) @@ -195,24 +201,24 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { Module: title, Headers: headerFiles, } - err = writeFile(buildTemp+"/Versions/A/Modules/module.modulemap", func(w io.Writer) error { + err = writeFile(filepath.Join(versionsADir, "Modules", "module.modulemap"), func(w io.Writer) error { return iosModuleMapTmpl.Execute(w, mmVals) }) if err != nil { return err } - err = symlink("Versions/Current/Modules", buildTemp+"/Modules") + err = symlink(filepath.Join("Versions/Current/Modules"), filepath.Join(frameworkDir, "Modules")) if err != nil { return err } } } - // Finally combine ios/simulator/catalyst framework to xcframework + // Finally combine all frameworks to an XCFramework xcframeworkArgs := []string{"-create-xcframework"} - for _, target := range iOSTargets { - xcframeworkArgs = append(xcframeworkArgs, "-framework", tmpdir+"/"+target+"/"+title+".framework") + for _, dir := range frameworkDirs { + xcframeworkArgs = append(xcframeworkArgs, "-framework", dir) } xcframeworkArgs = append(xcframeworkArgs, "-output", buildO) From 964653afb4af824088a0fe93967fed4b00d3a457 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:43:36 -0700 Subject: [PATCH 22/24] cmd/gomobile: remove a few single-use variables --- cmd/gomobile/bind_iosapp.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index ba58a0130..93c9dc9f4 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -119,8 +119,7 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { if err := mkdir(versionsAHeadersDir); err != nil { return err } - versionsCurrentDir := filepath.Join(versionsDir, "Current") - if err := symlink("A", versionsCurrentDir); err != nil { + if err := symlink("A", filepath.Join(versionsDir, "Current")); err != nil { return err } if err := symlink("Versions/Current/Headers", filepath.Join(frameworkDir, "Headers")); err != nil { @@ -178,15 +177,13 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } } - resourcesADir := filepath.Join(versionsADir, "Resources") - resourcesDir := filepath.Join(frameworkDir, "Resources") - if err := mkdir(resourcesADir); err != nil { + if err := mkdir(filepath.Join(versionsADir, "Resources")); err != nil { return err } if err := symlink("Versions/Current/Resources", filepath.Join(frameworkDir, "Resources")); err != nil { return err } - err = writeFile(filepath.Join(resourcesDir, "Info.plist"), func(w io.Writer) error { + err = writeFile(filepath.Join(frameworkDir, "Resources", "Info.plist"), func(w io.Writer) error { _, err := w.Write([]byte(iosBindInfoPlist)) return err }) From b39ae241f6f86637fd5b5bd3344094b3abaff192 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:44:27 -0700 Subject: [PATCH 23/24] cmd/gomobile: remove slice assignment optimization Just use append. --- cmd/gomobile/bind_iosapp.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go index 93c9dc9f4..83d9e3f10 100644 --- a/cmd/gomobile/bind_iosapp.go +++ b/cmd/gomobile/bind_iosapp.go @@ -138,9 +138,9 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { } // Copy header file next to output archive. - headerFiles := make([]string, len(fileBases)) + var headerFiles []string if len(fileBases) == 1 { - headerFiles[0] = title + ".h" + headerFiles = append(headerFiles, title+".h") err := copyFile( filepath.Join(versionsAHeadersDir, title+".h"), filepath.Join(srcDir, bindPrefix+title+".objc.h"), @@ -149,8 +149,8 @@ func goIOSBind(gobind string, pkgs []*packages.Package, archs []string) error { return err } } else { - for i, fileBase := range fileBases { - headerFiles[i] = fileBase + ".objc.h" + for _, fileBase := range fileBases { + headerFiles = append(headerFiles, fileBase+".objc.h") err := copyFile( filepath.Join(versionsAHeadersDir, fileBase+".objc.h"), filepath.Join(srcDir, fileBase+".objc.h"), From 623f8f38653c856d2cd07e721f0932e515b50d02 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Fri, 9 Jul 2021 14:46:16 -0700 Subject: [PATCH 24/24] go.sum: go mod tidy; CL feedback --- go.sum | 1 - 1 file changed, 1 deletion(-) diff --git a/go.sum b/go.sum index 536cecdfd..79a6d20d1 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=