Merge "Add Darwin x86_64+arm64 universal binary support" am: ce69757379
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1884611 Change-Id: I54226fc10b6e7265c9378df3e9634c793a61a12e
This commit is contained in:
@@ -566,6 +566,8 @@ func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
|
|||||||
return variants
|
return variants
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}
|
||||||
|
|
||||||
// archMutator splits a module into a variant for each Target requested by the module. Target selection
|
// archMutator splits a module into a variant for each Target requested by the module. Target selection
|
||||||
// for a module is in three levels, OsClass, multilib, and then Target.
|
// for a module is in three levels, OsClass, multilib, and then Target.
|
||||||
// OsClass selection is determined by:
|
// OsClass selection is determined by:
|
||||||
@@ -652,7 +654,7 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) {
|
|||||||
prefer32 := os == Windows
|
prefer32 := os == Windows
|
||||||
|
|
||||||
// Determine the multilib selection for this module.
|
// Determine the multilib selection for this module.
|
||||||
multilib, extraMultilib := decodeMultilib(base, os.Class)
|
multilib, extraMultilib := decodeMultilib(base, os)
|
||||||
|
|
||||||
// Convert the multilib selection into a list of Targets.
|
// Convert the multilib selection into a list of Targets.
|
||||||
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
|
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
|
||||||
@@ -702,6 +704,16 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) {
|
|||||||
m.base().commonProperties.SkipInstall = true
|
m.base().commonProperties.SkipInstall = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a dependency for Darwin Universal binaries from the primary to secondary
|
||||||
|
// architecture. The module itself will be responsible for calling lipo to merge the outputs.
|
||||||
|
if os == Darwin {
|
||||||
|
if multilib == "darwin_universal" && len(modules) == 2 {
|
||||||
|
mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[1], modules[0])
|
||||||
|
} else if multilib == "darwin_universal_common_first" && len(modules) == 3 {
|
||||||
|
mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[2], modules[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
|
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
|
||||||
@@ -717,9 +729,9 @@ func addTargetProperties(m Module, target Target, multiTargets []Target, primary
|
|||||||
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
|
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
|
||||||
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
|
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
|
||||||
// the actual multilib in extraMultilib.
|
// the actual multilib in extraMultilib.
|
||||||
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
|
func decodeMultilib(base *ModuleBase, os OsType) (multilib, extraMultilib string) {
|
||||||
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
|
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
|
||||||
switch class {
|
switch os.Class {
|
||||||
case Device:
|
case Device:
|
||||||
multilib = String(base.commonProperties.Target.Android.Compile_multilib)
|
multilib = String(base.commonProperties.Target.Android.Compile_multilib)
|
||||||
case Host:
|
case Host:
|
||||||
@@ -737,6 +749,26 @@ func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if base.commonProperties.UseTargetVariants {
|
if base.commonProperties.UseTargetVariants {
|
||||||
|
// Darwin has the concept of "universal binaries" which is implemented in Soong by
|
||||||
|
// building both x86_64 and arm64 variants, and having select module types know how to
|
||||||
|
// merge the outputs of their corresponding variants together into a final binary. Most
|
||||||
|
// module types don't need to understand this logic, as we only build a small portion
|
||||||
|
// of the tree for Darwin, and only module types writing macho files need to do the
|
||||||
|
// merging.
|
||||||
|
//
|
||||||
|
// This logic is not enabled for:
|
||||||
|
// "common", as it's not an arch-specific variant
|
||||||
|
// "32", as Darwin never has a 32-bit variant
|
||||||
|
// !UseTargetVariants, as the module has opted into handling the arch-specific logic on
|
||||||
|
// its own.
|
||||||
|
if os == Darwin && multilib != "common" && multilib != "32" {
|
||||||
|
if multilib == "common_first" {
|
||||||
|
multilib = "darwin_universal_common_first"
|
||||||
|
} else {
|
||||||
|
multilib = "darwin_universal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return multilib, ""
|
return multilib, ""
|
||||||
} else {
|
} else {
|
||||||
// For app modules a single arch variant will be created per OS class which is expected to handle all the
|
// For app modules a single arch variant will be created per OS class which is expected to handle all the
|
||||||
@@ -1793,6 +1825,15 @@ func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]
|
|||||||
if len(buildTargets) == 0 {
|
if len(buildTargets) == 0 {
|
||||||
buildTargets = filterMultilibTargets(targets, "lib64")
|
buildTargets = filterMultilibTargets(targets, "lib64")
|
||||||
}
|
}
|
||||||
|
case "darwin_universal":
|
||||||
|
buildTargets = filterMultilibTargets(targets, "lib64")
|
||||||
|
// Reverse the targets so that the first architecture can depend on the second
|
||||||
|
// architecture module in order to merge the outputs.
|
||||||
|
reverseSliceInPlace(buildTargets)
|
||||||
|
case "darwin_universal_common_first":
|
||||||
|
archTargets := filterMultilibTargets(targets, "lib64")
|
||||||
|
reverseSliceInPlace(archTargets)
|
||||||
|
buildTargets = append(getCommonTargets(targets), archTargets...)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
|
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
|
||||||
multilib)
|
multilib)
|
||||||
|
@@ -2015,6 +2015,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
|
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
|
||||||
// nothing
|
// nothing
|
||||||
|
} else if depTag == android.DarwinUniversalVariantTag {
|
||||||
|
// nothing
|
||||||
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
|
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
|
||||||
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
|
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
|
||||||
}
|
}
|
||||||
|
@@ -345,6 +345,12 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
|
|||||||
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-dynamic-linker")
|
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-dynamic-linker")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() {
|
||||||
|
fatOutputFile := outputFile
|
||||||
|
outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName)
|
||||||
|
transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path())
|
||||||
|
}
|
||||||
|
|
||||||
builderFlags := flagsToBuilderFlags(flags)
|
builderFlags := flagsToBuilderFlags(flags)
|
||||||
stripFlags := flagsToStripFlags(flags)
|
stripFlags := flagsToStripFlags(flags)
|
||||||
if binary.stripper.NeedsStrip(ctx) {
|
if binary.stripper.NeedsStrip(ctx) {
|
||||||
|
@@ -165,6 +165,12 @@ var (
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
darwinLipo = pctx.AndroidStaticRule("darwinLipo",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: "${config.MacLipoPath} -create -output $out $in",
|
||||||
|
CommandDeps: []string{"${config.MacLipoPath}"},
|
||||||
|
})
|
||||||
|
|
||||||
_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
|
_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
|
||||||
|
|
||||||
// Rule to repack an archive (.a) file with a subset of object files.
|
// Rule to repack an archive (.a) file with a subset of object files.
|
||||||
@@ -1059,6 +1065,15 @@ func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) {
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: darwinLipo,
|
||||||
|
Description: "lipo " + outputFile.Base(),
|
||||||
|
Output: outputFile,
|
||||||
|
Inputs: inputFiles,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Registers build statement to zip one or more coverage files.
|
// Registers build statement to zip one or more coverage files.
|
||||||
func transformCoverageFilesToZip(ctx android.ModuleContext,
|
func transformCoverageFilesToZip(ctx android.ModuleContext,
|
||||||
inputs Objects, baseName string) android.OptionalPath {
|
inputs Objects, baseName string) android.OptionalPath {
|
||||||
|
9
cc/cc.go
9
cc/cc.go
@@ -167,6 +167,10 @@ type PathDeps struct {
|
|||||||
|
|
||||||
// Path to the dynamic linker binary
|
// Path to the dynamic linker binary
|
||||||
DynamicLinker android.OptionalPath
|
DynamicLinker android.OptionalPath
|
||||||
|
|
||||||
|
// For Darwin builds, the path to the second architecture's output that should
|
||||||
|
// be combined with this architectures's output into a FAT MachO file.
|
||||||
|
DarwinSecondArchOutput android.OptionalPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
|
// LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
|
||||||
@@ -2584,6 +2588,11 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
depName := ctx.OtherModuleName(dep)
|
depName := ctx.OtherModuleName(dep)
|
||||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||||
|
|
||||||
|
if depTag == android.DarwinUniversalVariantTag {
|
||||||
|
depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ccDep, ok := dep.(LinkableInterface)
|
ccDep, ok := dep.(LinkableInterface)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
||||||
|
@@ -87,6 +87,10 @@ func init() {
|
|||||||
return getMacTools(ctx).arPath
|
return getMacTools(ctx).arPath
|
||||||
})
|
})
|
||||||
|
|
||||||
|
pctx.VariableFunc("MacLipoPath", func(ctx android.PackageVarContext) string {
|
||||||
|
return getMacTools(ctx).lipoPath
|
||||||
|
})
|
||||||
|
|
||||||
pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
|
pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
|
||||||
return getMacTools(ctx).stripPath
|
return getMacTools(ctx).stripPath
|
||||||
})
|
})
|
||||||
@@ -118,6 +122,7 @@ type macPlatformTools struct {
|
|||||||
|
|
||||||
sdkRoot string
|
sdkRoot string
|
||||||
arPath string
|
arPath string
|
||||||
|
lipoPath string
|
||||||
stripPath string
|
stripPath string
|
||||||
toolPath string
|
toolPath string
|
||||||
}
|
}
|
||||||
@@ -157,6 +162,7 @@ func getMacTools(ctx android.PathContext) *macPlatformTools {
|
|||||||
macTools.sdkRoot = xcrun("--show-sdk-path")
|
macTools.sdkRoot = xcrun("--show-sdk-path")
|
||||||
|
|
||||||
macTools.arPath = xcrun("--find", "ar")
|
macTools.arPath = xcrun("--find", "ar")
|
||||||
|
macTools.lipoPath = xcrun("--find", "lipo")
|
||||||
macTools.stripPath = xcrun("--find", "strip")
|
macTools.stripPath = xcrun("--find", "strip")
|
||||||
macTools.toolPath = filepath.Dir(xcrun("--find", "ld"))
|
macTools.toolPath = filepath.Dir(xcrun("--find", "ld"))
|
||||||
})
|
})
|
||||||
|
@@ -1429,6 +1429,12 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
|
|||||||
|
|
||||||
builderFlags := flagsToBuilderFlags(flags)
|
builderFlags := flagsToBuilderFlags(flags)
|
||||||
|
|
||||||
|
if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() {
|
||||||
|
fatOutputFile := outputFile
|
||||||
|
outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName)
|
||||||
|
transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path())
|
||||||
|
}
|
||||||
|
|
||||||
// Optimize out relinking against shared libraries whose interface hasn't changed by
|
// Optimize out relinking against shared libraries whose interface hasn't changed by
|
||||||
// depending on a table of contents file instead of the library itself.
|
// depending on a table of contents file instead of the library itself.
|
||||||
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
|
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
|
||||||
|
Reference in New Issue
Block a user