Skip to content

Commit 708f5c6

Browse files
committed
cmd/gomobile: remove 'iossimulator' as a targetable platform
This modifies the iOS/Darwin build code to generate a unique framework per SDK, because Xcode won't build a framework with multiple SDKs, or merge different frameworks with the same SDK, but different architectures. The iPhone Simulator is technically a different SDK, so it needs its own framework.
1 parent 77eab9e commit 708f5c6

File tree

5 files changed

+63
-90
lines changed

5 files changed

+63
-90
lines changed

cmd/gomobile/bind_darwinapp.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,15 @@ func goDarwinbind(gobind string, pkgs []*packages.Package, targetPlatforms, targ
4343
return err
4444
}
4545

46-
// create separate framework for ios,simulator and catalyst
47-
// every target has at least one arch (arm64 and x86_64)
4846
var frameworkDirs []string
47+
frameworkArchCount := map[string]int{}
4948
for _, platform := range targetPlatforms {
5049
// Catalyst support requires iOS 13+
5150
v, _ := strconv.ParseFloat(buildIOSVersion, 64)
5251
if platform == "maccatalyst" && v < 13.0 {
5352
return errors.New("catalyst requires -iosversion=13 or higher")
5453
}
5554

56-
frameworkDir := filepath.Join(tmpdir, platform, title+".framework")
57-
frameworkDirs = append(frameworkDirs, frameworkDir)
58-
5955
outDir := filepath.Join(tmpdir, platform)
6056
outSrcDir := filepath.Join(outDir, "src")
6157
gobindDir := filepath.Join(outSrcDir, "gobind")
@@ -80,30 +76,33 @@ func goDarwinbind(gobind string, pkgs []*packages.Package, targetPlatforms, targ
8076
return err
8177
}
8278

83-
var numArchs int
8479
for _, arch := range platformArchs(platform) {
8580
// Skip unrequested architectures
8681
if !contains(targetArchs, arch) {
8782
continue
8883
}
89-
numArchs++
84+
85+
env := darwinEnv[platform+"/"+arch][:]
86+
sdk := getenv(env, "DARWIN_SDK")
87+
88+
frameworkDir := filepath.Join(tmpdir, platform, sdk, title+".framework")
89+
frameworkDirs = append(frameworkDirs, frameworkDir)
90+
frameworkArchCount[frameworkDir] = frameworkArchCount[frameworkDir] + 1
9091

9192
fileBases := make([]string, len(pkgs)+1)
9293
for i, pkg := range pkgs {
9394
fileBases[i] = bindPrefix + strings.Title(pkg.Name)
9495
}
9596
fileBases[len(fileBases)-1] = "Universe"
9697

97-
env := darwinEnv[platform+"/"+arch][:]
98+
// Add the generated packages to GOPATH for reverse bindings.
99+
gopath := fmt.Sprintf("GOPATH=%s%c%s", outDir, filepath.ListSeparator, goEnv("GOPATH"))
100+
env = append(env, gopath)
98101

99102
if err := writeGoMod(outDir, platform, arch); err != nil {
100103
return err
101104
}
102105

103-
// Add the generated packages to GOPATH for reverse bindings.
104-
gopath := fmt.Sprintf("GOPATH=%s%c%s", outDir, filepath.ListSeparator, goEnv("GOPATH"))
105-
env = append(env, gopath)
106-
107106
// Run `go mod tidy` to force to create go.sum.
108107
// Without go.sum, `go build` fails as of Go 1.16.
109108
if modulesUsed {
@@ -120,7 +119,7 @@ func goDarwinbind(gobind string, pkgs []*packages.Package, targetPlatforms, targ
120119
versionsDir := filepath.Join(frameworkDir, "Versions")
121120
versionsADir := filepath.Join(versionsDir, "A")
122121
titlePath := filepath.Join(versionsADir, title)
123-
if numArchs > 1 {
122+
if frameworkArchCount[frameworkDir] > 1 {
124123
// Not the first static lib, attach to a fat library and skip create headers
125124
fatCmd := exec.Command(
126125
"xcrun",

cmd/gomobile/bind_test.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -197,27 +197,26 @@ WORK=$WORK
197197
rm -r -f "{{.Output}}.xcframework"
198198
GOOS=ios CGO_ENABLED=1 gobind -lang=go,objc -outdir=$WORK/ios -tags=ios{{if .Prefix}} -prefix={{.Prefix}}{{end}} golang.org/x/mobile/asset
199199
mkdir -p $WORK/ios/src
200-
PWD=$WORK/ios/src GOOS=ios GOARCH=arm64 GOFLAGS=-tags=ios CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 GOPATH=$WORK/ios:$GOPATH go mod tidy
201-
PWD=$WORK/ios/src GOOS=ios GOARCH=arm64 GOFLAGS=-tags=ios CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 GOPATH=$WORK/ios:$GOPATH go build -x -buildmode=c-archive -o $WORK/{{.Output}}-ios-arm64.a ./gobind
202-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Headers
203-
ln -s A $WORK/ios/{{.Output}}.framework/Versions/Current
204-
ln -s Versions/Current/Headers $WORK/ios/{{.Output}}.framework/Headers
205-
ln -s Versions/Current/{{.Output}} $WORK/ios/{{.Output}}.framework/{{.Output}}
206-
xcrun lipo -create -arch arm64 $WORK/{{.Output}}-ios-arm64.a -o $WORK/ios/{{.Output}}.framework/Versions/A/{{.Output}}
207-
cp $WORK/ios/src/gobind/{{.Prefix}}Asset.objc.h $WORK/ios/{{.Output}}.framework/Versions/A/Headers/{{.Prefix}}Asset.objc.h
208-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Headers
209-
cp $WORK/ios/src/gobind/Universe.objc.h $WORK/ios/{{.Output}}.framework/Versions/A/Headers/Universe.objc.h
210-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Headers
211-
cp $WORK/ios/src/gobind/ref.h $WORK/ios/{{.Output}}.framework/Versions/A/Headers/ref.h
212-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Headers
213-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Headers
214-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Resources
215-
ln -s Versions/Current/Resources $WORK/ios/{{.Output}}.framework/Resources
216-
mkdir -p $WORK/ios/{{.Output}}.framework/Resources
217-
mkdir -p $WORK/ios/{{.Output}}.framework/Versions/A/Modules
218-
ln -s Versions/Current/Modules $WORK/ios/{{.Output}}.framework/Modules
219-
GOOS=ios CGO_ENABLED=1 gobind -lang=go,objc -outdir=$WORK/iossimulator -tags=ios,iossimulator{{if .Prefix}} -prefix={{.Prefix}}{{end}} golang.org/x/mobile/asset
220-
xcodebuild -create-xcframework -framework $WORK/ios/{{.Output}}.framework -framework $WORK/iossimulator/{{.Output}}.framework -output {{.Output}}.xcframework
200+
PWD=$WORK/ios/src GOOS=ios GOARCH=arm64 GOFLAGS=-tags=ios CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 DARWIN_SDK=iphoneos GOPATH=$WORK/ios:$GOPATH go mod tidy
201+
PWD=$WORK/ios/src GOOS=ios GOARCH=arm64 GOFLAGS=-tags=ios CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=13.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 DARWIN_SDK=iphoneos GOPATH=$WORK/ios:$GOPATH go build -x -buildmode=c-archive -o $WORK/{{.Output}}-ios-arm64.a ./gobind
202+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers
203+
ln -s A $WORK/ios/iphoneos/{{.Output}}.framework/Versions/Current
204+
ln -s Versions/Current/Headers $WORK/ios/iphoneos/{{.Output}}.framework/Headers
205+
ln -s Versions/Current/{{.Output}} $WORK/ios/iphoneos/{{.Output}}.framework/{{.Output}}
206+
xcrun lipo -create -arch arm64 $WORK/{{.Output}}-ios-arm64.a -o $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/{{.Output}}
207+
cp $WORK/ios/src/gobind/{{.Prefix}}Asset.objc.h $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers/{{.Prefix}}Asset.objc.h
208+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers
209+
cp $WORK/ios/src/gobind/Universe.objc.h $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers/Universe.objc.h
210+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers
211+
cp $WORK/ios/src/gobind/ref.h $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers/ref.h
212+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers
213+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Headers
214+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Resources
215+
ln -s Versions/Current/Resources $WORK/ios/iphoneos/{{.Output}}.framework/Resources
216+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Resources
217+
mkdir -p $WORK/ios/iphoneos/{{.Output}}.framework/Versions/A/Modules
218+
ln -s Versions/Current/Modules $WORK/ios/iphoneos/{{.Output}}.framework/Modules
219+
xcodebuild -create-xcframework -framework $WORK/ios/iphoneos/{{.Output}}.framework -output {{.Output}}.xcframework
221220
`))
222221

223222
func TestBindIOSAll(t *testing.T) {

cmd/gomobile/build.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -382,20 +382,14 @@ func parseBuildTarget(buildTarget string) (targetPlatforms, targetArchs []string
382382
return nil, nil, fmt.Errorf(`cannot mix android and darwin platforms`)
383383
}
384384

385-
expanded, err := expandPlatform(platform)
386-
if err != nil {
387-
return nil, nil, err
388-
}
389-
for _, p := range expanded {
390-
if !platforms[p] {
391-
platforms[p] = true
392-
targetPlatforms = append(targetPlatforms, p)
393-
if !hasArch {
394-
for _, arch := range platformArchs(p) {
395-
if !archs[arch] {
396-
archs[arch] = true
397-
targetArchs = append(targetArchs, arch)
398-
}
385+
if !platforms[platform] {
386+
platforms[platform] = true
387+
targetPlatforms = append(targetPlatforms, platform)
388+
if !hasArch {
389+
for _, arch := range platformArchs(platform) {
390+
if !archs[arch] {
391+
archs[arch] = true
392+
targetArchs = append(targetArchs, arch)
399393
}
400394
}
401395
}

cmd/gomobile/build_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ func TestParseBuildTargetFlag(t *testing.T) {
127127
{"android,android/arm", false, "android", androidArchs},
128128
{"android/arm", false, "android", "arm"},
129129

130-
{"ios", false, "ios,iossimulator", "arm64,amd64"},
131-
{"ios,ios/arm64", false, "ios,iossimulator", "arm64,amd64"},
132-
{"ios/arm64", false, "ios,iossimulator", "arm64"},
130+
{"ios", false, "ios", "arm64,amd64"},
131+
{"ios,ios/arm64", false, "ios", "arm64,amd64"},
132+
{"ios/arm64", false, "ios", "arm64"},
133133

134134
{"", true, "", ""},
135135
{"linux", true, "", ""},

cmd/gomobile/env.go

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,6 @@ var (
2525
bitcodeEnabled bool
2626
)
2727

28-
// expandPlatform returns a list of currently-supported SDKs for platform.
29-
func expandPlatform(platform string) (platforms []string, _ error) {
30-
switch platform {
31-
case "android":
32-
return []string{"android"}, nil
33-
case "ios":
34-
// Preserve existing -target=ios behavior
35-
return []string{"ios", "iossimulator"}, nil
36-
case "iossimulator":
37-
return []string{"iossimulator"}, nil
38-
case "macos":
39-
return []string{"macos"}, nil
40-
case "maccatalyst":
41-
return []string{"maccatalyst"}, nil
42-
default:
43-
return nil, fmt.Errorf("unexpected platform: %s", platform)
44-
}
45-
}
46-
4728
func isAndroidPlatform(platform string) bool {
4829
return platform == "android"
4930
}
@@ -52,16 +33,12 @@ func isDarwinPlatform(platform string) bool {
5233
return contains(darwinPlatforms, platform)
5334
}
5435

55-
var darwinPlatforms = []string{"ios", "iossimulator", "maccatalyst", "macos"}
36+
var darwinPlatforms = []string{"ios", "maccatalyst", "macos"}
5637

5738
func platformArchs(platform string) []string {
5839
switch platform {
5940
case "ios":
60-
// Only build iOS on arm64
61-
return []string{"arm64"}
62-
case "iossimulator":
63-
// Only build iOS simulator on amd64
64-
return []string{"amd64"}
41+
return []string{"arm64", "amd64"}
6542
case "macos", "maccatalyst":
6643
return []string{"arm64", "amd64"}
6744
case "android":
@@ -80,7 +57,7 @@ func platformOS(platform string) string {
8057
switch platform {
8158
case "android":
8259
return "android"
83-
case "ios", "iossimulator":
60+
case "ios":
8461
return "ios"
8562
case "macos", "maccatalyst":
8663
return "darwin"
@@ -95,8 +72,6 @@ func platformTags(platform string) []string {
9572
return []string{"android"}
9673
case "ios":
9774
return []string{"ios"}
98-
case "iossimulator":
99-
return []string{"ios", "iossimulator"}
10075
case "macos":
10176
return []string{"macos"}
10277
case "maccatalyst":
@@ -225,20 +200,25 @@ func envInit() (err error) {
225200
for _, platform := range darwinPlatforms {
226201
for _, arch := range platformArchs(platform) {
227202
var env []string
228-
var goos, clang, cflags string
203+
var goos, sdk, clang, cflags string
229204
var err error
230205
switch platform {
231206
case "ios":
232207
goos = "ios"
233-
clang, cflags, err = envClang("iphoneos")
234-
cflags += " -miphoneos-version-min=" + buildIOSVersion
235-
case "iossimulator":
236-
goos = "ios"
237-
clang, cflags, err = envClang("iphonesimulator")
238-
cflags += " -mios-simulator-version-min=" + buildIOSVersion
208+
switch arch {
209+
case "arm64":
210+
sdk = "iphoneos"
211+
clang, cflags, err = envClang(sdk)
212+
cflags += " -miphoneos-version-min=" + buildIOSVersion
213+
case "amd64":
214+
sdk = "iphonesimulator"
215+
clang, cflags, err = envClang(sdk)
216+
cflags += " -mios-simulator-version-min=" + buildIOSVersion
217+
}
239218
case "maccatalyst":
240219
goos = "darwin"
241-
clang, cflags, err = envClang("macosx")
220+
sdk = "macosx"
221+
clang, cflags, err = envClang(sdk)
242222
switch arch {
243223
case "amd64":
244224
cflags += " -target x86_64-apple-ios" + buildIOSVersion + "-macabi"
@@ -248,10 +228,10 @@ func envInit() (err error) {
248228
// cflags += " -UTARGET_OS_IPHONE"
249229
case "macos":
250230
goos = "darwin"
251-
// Note: the SDK is called "macosx", not "macos"
252-
clang, cflags, err = envClang("macosx")
231+
sdk = "macosx" // Note: the SDK is called "macosx", not "macos"
232+
clang, cflags, err = envClang(sdk)
253233
default:
254-
panic(fmt.Errorf("unknown darwin target: %q", arch))
234+
panic(fmt.Errorf("unknown darwin target: %s/%s", platform, arch))
255235
}
256236

257237
if err != nil {
@@ -271,6 +251,7 @@ func envInit() (err error) {
271251
"CGO_CXXFLAGS="+cflags+" -arch "+archClang(arch),
272252
"CGO_LDFLAGS="+cflags+" -arch "+archClang(arch),
273253
"CGO_ENABLED=1",
254+
"DARWIN_SDK="+sdk,
274255
)
275256
darwinEnv[platform+"/"+arch] = env
276257
}

0 commit comments

Comments
 (0)