Merge "WriteFileRule: Chunk long content and merge them to result"
diff --git a/android/androidmk.go b/android/androidmk.go
index a670656..6ab4a24 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// This file offers AndroidMkEntriesProvider, which individual modules implement to output
+// Android.mk entries that contain information about the modules built through Soong. Kati reads
+// and combines them with the legacy Make-based module definitions to produce the complete view of
+// the source tree, which makes this a critical point of Make-Soong interoperability.
+//
+// Naturally, Soong-only builds do not rely on this mechanism.
+
package android
import (
@@ -36,8 +43,8 @@
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
}
-// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to
-// use the Custom function.
+// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
+// Custom function. It's easier to use and test.
type AndroidMkDataProvider interface {
AndroidMk() AndroidMkData
BaseModuleName() string
@@ -63,37 +70,82 @@
type AndroidMkExtraFunc func(w io.Writer, outputFile Path)
-// Allows modules to customize their Android*.mk output.
+// Interface for modules to declare their Android.mk outputs. Note that every module needs to
+// implement this in order to be included in the final Android-<product_name>.mk output, even if
+// they only need to output the common set of entries without any customizations.
type AndroidMkEntriesProvider interface {
+ // Returns AndroidMkEntries objects that contain all basic info plus extra customization data
+ // if needed. This is the core func to implement.
+ // Note that one can return multiple objects. For example, java_library may return an additional
+ // AndroidMkEntries object for its hostdex sub-module.
AndroidMkEntries() []AndroidMkEntries
+ // Modules don't need to implement this as it's already implemented by ModuleBase.
+ // AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules
+ // e.g. Prebuilts, override the Name() func and return modified names.
+ // If a different name is preferred, use SubName or OverrideName in AndroidMkEntries.
BaseModuleName() string
}
+// The core data struct that modules use to provide their Android.mk data.
type AndroidMkEntries struct {
- Class string
- SubName string
- OverrideName string
- DistFiles TaggedDistFiles
- OutputFile OptionalPath
- Disabled bool
- Include string
- Required []string
- Host_required []string
+ // Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC
+ Class string
+ // Optional suffix to append to the module name. Useful when a module wants to return multiple
+ // AndroidMkEntries objects. For example, when a java_library returns an additional entry for
+ // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
+ // different name than the parent's.
+ SubName string
+ // If set, this value overrides the base module name. SubName is still appended.
+ OverrideName string
+ // Dist files to output
+ DistFiles TaggedDistFiles
+ // The output file for Kati to process and/or install. If absent, the module is skipped.
+ OutputFile OptionalPath
+ // If true, the module is skipped and does not appear on the final Android-<product name>.mk
+ // file. Useful when a module needs to be skipped conditionally.
+ Disabled bool
+ // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_prebuilt.mk
+ // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
+ Include string
+ // Required modules that need to be built and included in the final build output when building
+ // this module.
+ Required []string
+ // Required host modules that need to be built and included in the final build output when
+ // building this module.
+ Host_required []string
+ // Required device modules that need to be built and included in the final build output when
+ // building this module.
Target_required []string
header bytes.Buffer
footer bytes.Buffer
+ // Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are
+ // accepted so that common logic can be factored out as a shared func.
ExtraEntries []AndroidMkExtraEntriesFunc
+ // Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc,
+ // which simply sets Make variable values, this can be used for anything since it can write any
+ // Make statements directly to the final Android-*.mk file.
+ // Primarily used to call macros or declare/update Make targets.
ExtraFooters []AndroidMkExtraFootersFunc
- EntryMap map[string][]string
+ // A map that holds the up-to-date Make variable values. Can be accessed from tests.
+ EntryMap map[string][]string
+ // A list of EntryMap keys in insertion order. This serves a few purposes:
+ // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
+ // the outputted Android-*.mk file may change even though there have been no content changes.
+ // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
+ // without worrying about the variables being mixed up in the actual mk file.
+ // 3. Makes troubleshooting and spotting errors easier.
entryOrder []string
}
type AndroidMkExtraEntriesFunc func(entries *AndroidMkEntries)
type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries)
+// Utility funcs to manipulate Android.mk variable entries.
+
+// SetString sets a Make variable with the given name to the given value.
func (a *AndroidMkEntries) SetString(name, value string) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -101,6 +153,7 @@
a.EntryMap[name] = []string{value}
}
+// SetPath sets a Make variable with the given name to the given path string.
func (a *AndroidMkEntries) SetPath(name string, path Path) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -108,12 +161,15 @@
a.EntryMap[name] = []string{path.String()}
}
+// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
+// It is a no-op if the given path is invalid.
func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) {
if path.Valid() {
a.SetPath(name, path.Path())
}
}
+// AddPath appends the given path string to a Make variable with the given name.
func (a *AndroidMkEntries) AddPath(name string, path Path) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -121,12 +177,15 @@
a.EntryMap[name] = append(a.EntryMap[name], path.String())
}
+// AddOptionalPath appends the given path string to a Make variable with the given name if it is
+// valid. It is a no-op if the given path is invalid.
func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
if path.Valid() {
a.AddPath(name, path.Path())
}
}
+// SetPaths sets a Make variable with the given name to a slice of the given path strings.
func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -134,12 +193,15 @@
a.EntryMap[name] = paths.Strings()
}
+// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
+// only if there are a non-zero amount of paths.
func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
if len(paths) > 0 {
a.SetPaths(name, paths)
}
}
+// AddPaths appends the given path strings to a Make variable with the given name.
func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -147,6 +209,8 @@
a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
}
+// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
+// It is a no-op if the given flag is false.
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
if flag {
if _, ok := a.EntryMap[name]; !ok {
@@ -156,6 +220,7 @@
}
}
+// SetBool sets a Make variable with the given name to if the given bool flag value.
func (a *AndroidMkEntries) SetBool(name string, flag bool) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@@ -167,6 +232,7 @@
}
}
+// AddStrings appends the given strings to a Make variable with the given name.
func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
if len(value) == 0 {
return
@@ -368,6 +434,8 @@
return generateDistContributionsForMake(distContributions)
}
+// fillInEntries goes through the common variable processing and calls the extra data funcs to
+// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
a.EntryMap = make(map[string][]string)
amod := mod.(Module).base()
@@ -488,6 +556,8 @@
}
}
+// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
+// given Writer object.
func (a *AndroidMkEntries) write(w io.Writer) {
if a.Disabled {
return
@@ -508,6 +578,8 @@
return strings.Split(string(a.footer.Bytes()), "\n")
}
+// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into
+// the final Android-<product_name>.mk file output.
func AndroidMkSingleton() Singleton {
return &androidMkSingleton{}
}
@@ -515,6 +587,7 @@
type androidMkSingleton struct{}
func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // Skip if Soong wasn't invoked from Make.
if !ctx.Config().KatiEnabled() {
return
}
@@ -525,6 +598,8 @@
androidMkModulesList = append(androidMkModulesList, module)
})
+ // Sort the module list by the module names to eliminate random churns, which may erroneously
+ // invoke additional build processes.
sort.SliceStable(androidMkModulesList, func(i, j int) bool {
return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
})
@@ -617,6 +692,8 @@
}
}
+// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
+// m by making them phony targets.
func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
goBinary bootstrap.GoBinaryTool) error {
@@ -649,6 +726,8 @@
data.Target_required = data.Entries.Target_required
}
+// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
+// instead.
func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
provider AndroidMkDataProvider) error {
@@ -695,6 +774,8 @@
return nil
}
+// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
+// instead.
func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
if data.Disabled {
return
@@ -742,11 +823,14 @@
module.Os() == LinuxBionic
}
+// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
+// to use this func.
func AndroidMkDataPaths(data []DataPath) []string {
var testFiles []string
for _, d := range data {
rel := d.SrcPath.Rel()
path := d.SrcPath.String()
+ // LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
if !strings.HasSuffix(path, rel) {
panic(fmt.Errorf("path %q does not end with %q", path, rel))
}
diff --git a/android/arch.go b/android/arch.go
index df407d4..34f9b29 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1337,17 +1337,6 @@
addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
- // An optional host target that uses the Bionic glibc runtime.
- if Bool(config.Host_bionic) {
- addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
- }
-
- // An optional cross-compiled host target that uses the Bionic glibc runtime on an arm64
- // architecture.
- if Bool(config.Host_bionic_arm64) {
- addTarget(LinuxBionic, "arm64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
- }
-
// Optional cross-compiled host targets, generally Windows.
if String(variables.CrossHost) != "" {
crossHostOs := osByName(*variables.CrossHost)
@@ -1437,53 +1426,6 @@
abi []string
}
-// getMegaDeviceConfig returns a list of archConfigs for every architecture simultaneously.
-func getMegaDeviceConfig() []archConfig {
- return []archConfig{
- {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a9", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a15", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a53", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a53.a57", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
- {"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
- {"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
- {"arm64", "armv8-2a-dotprod", "cortex-a55", []string{"arm64-v8a"}},
- {"arm64", "armv8-2a-dotprod", "cortex-a75", []string{"arm64-v8a"}},
- {"arm64", "armv8-2a-dotprod", "cortex-a76", []string{"arm64-v8a"}},
- {"x86", "", "", []string{"x86"}},
- {"x86", "atom", "", []string{"x86"}},
- {"x86", "haswell", "", []string{"x86"}},
- {"x86", "ivybridge", "", []string{"x86"}},
- {"x86", "sandybridge", "", []string{"x86"}},
- {"x86", "silvermont", "", []string{"x86"}},
- {"x86", "stoneyridge", "", []string{"x86"}},
- {"x86", "x86_64", "", []string{"x86"}},
- {"x86_64", "", "", []string{"x86_64"}},
- {"x86_64", "haswell", "", []string{"x86_64"}},
- {"x86_64", "ivybridge", "", []string{"x86_64"}},
- {"x86_64", "sandybridge", "", []string{"x86_64"}},
- {"x86_64", "silvermont", "", []string{"x86_64"}},
- {"x86_64", "stoneyridge", "", []string{"x86_64"}},
- }
-}
-
// getNdkAbisConfig returns a list of archConfigs for the ABIs supported by the NDK.
func getNdkAbisConfig() []archConfig {
return []archConfig{
diff --git a/android/config.go b/android/config.go
index 57ab70b..9882d55 100644
--- a/android/config.go
+++ b/android/config.go
@@ -54,28 +54,9 @@
isPreview: true,
}
-// configFileName is the name the file containing FileConfigurableOptions from
-// soong_ui for the soong_build primary builder.
-const configFileName = "soong.config"
-
-// productVariablesFileName contain the product configuration variables from soong_ui for the
-// soong_build primary builder and Kati.
+// The product variables file name, containing product config from Kati.
const productVariablesFileName = "soong.variables"
-// A FileConfigurableOptions contains options which can be configured by the
-// config file. These will be included in the config struct.
-type FileConfigurableOptions struct {
- Mega_device *bool `json:",omitempty"`
- Host_bionic *bool `json:",omitempty"`
- Host_bionic_arm64 *bool `json:",omitempty"`
-}
-
-// SetDefaultConfig resets the receiving FileConfigurableOptions to default
-// values.
-func (f *FileConfigurableOptions) SetDefaultConfig() {
- *f = FileConfigurableOptions{}
-}
-
// A Config object represents the entire build configuration for Android.
type Config struct {
*config
@@ -97,12 +78,8 @@
type VendorConfig soongconfig.SoongConfig
// Definition of general build configuration for soong_build. Some of these
-// configuration values are generated from soong_ui for soong_build,
-// communicated over JSON files like soong.config or soong.variables.
+// product configuration values are read from Kati-generated soong.variables.
type config struct {
- // Options configurable with soong.confg
- FileConfigurableOptions
-
// Options configurable with soong.variables
productVariables productVariables
@@ -113,7 +90,6 @@
// purposes.
BazelContext BazelContext
- ConfigFileName string
ProductVariablesFileName string
Targets map[OsType][]Target
@@ -170,11 +146,6 @@
}
func loadConfig(config *config) error {
- err := loadFromConfigFile(&config.FileConfigurableOptions, absolutePath(config.ConfigFileName))
- if err != nil {
- return err
- }
-
return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
}
@@ -384,7 +355,6 @@
func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) {
// Make a config with default options.
config := &config{
- ConfigFileName: filepath.Join(buildDir, configFileName),
ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
env: originalEnv,
@@ -439,9 +409,7 @@
targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
var archConfig []archConfig
- if Bool(config.Mega_device) {
- archConfig = getMegaDeviceConfig()
- } else if config.NdkAbis() {
+ if config.NdkAbis() {
archConfig = getNdkAbisConfig()
} else if config.AmlAbis() {
archConfig = getAmlAbisConfig()
@@ -864,11 +832,6 @@
return c.Targets[Android][0].Arch.ArchType
}
-func (c *config) SkipMegaDeviceInstall(path string) bool {
- return Bool(c.Mega_device) &&
- strings.HasPrefix(path, filepath.Join(c.buildDir, "target", "product"))
-}
-
func (c *config) SanitizeHost() []string {
return append([]string(nil), c.productVariables.SanitizeHost...)
}
diff --git a/android/config_test.go b/android/config_test.go
index 68f68a0..7bfc800 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -78,11 +78,6 @@
if err != nil {
t.Errorf(err.Error())
}
-
- validateConfigAnnotations(&FileConfigurableOptions{})
- if err != nil {
- t.Errorf(err.Error())
- }
}
func TestMissingVendorConfig(t *testing.T) {
diff --git a/android/module.go b/android/module.go
index d680baa..b6729c0 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2399,10 +2399,6 @@
if m.Config().KatiEnabled() && !m.InstallBypassMake() {
return true
}
-
- if m.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
- return true
- }
}
return false
diff --git a/cc/binary.go b/cc/binary.go
index fbd293e..fa3966f 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -373,7 +373,7 @@
if String(binary.Properties.Prefix_symbols) != "" {
afterPrefixSymbols := outputFile
outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
- TransformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile,
+ transformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile,
builderFlags, afterPrefixSymbols)
}
@@ -428,13 +428,13 @@
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
// Register link action.
- TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
+ transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
builderFlags, outputFile, nil)
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
- binary.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, binary.getStem(ctx))
+ binary.coverageOutputFile = transformCoverageFilesToZip(ctx, objs, binary.getStem(ctx))
// Need to determine symlinks early since some targets (ie APEX) need this
// information but will not call 'install'
diff --git a/cc/builder.go b/cc/builder.go
index 81c09b1..439e372 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -19,7 +19,6 @@
// functions.
import (
- "fmt"
"path/filepath"
"runtime"
"strings"
@@ -40,6 +39,7 @@
var (
pctx = android.NewPackageContext("android/soong/cc")
+ // Rule to invoke gcc with given command, flags, and dependencies. Outputs a .d depfile.
cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true},
blueprint.RuleParams{
Depfile: "${out}.d",
@@ -49,6 +49,7 @@
},
"ccCmd", "cFlags")
+ // Rule to invoke gcc with given command and flags, but no dependencies.
ccNoDeps = pctx.AndroidStaticRule("ccNoDeps",
blueprint.RuleParams{
Command: "$relPwd $ccCmd -c $cFlags -o $out $in",
@@ -56,6 +57,8 @@
},
"ccCmd", "cFlags")
+ // Rules to invoke ld to link binaries. Uses a .rsp file to list dependencies, as there may
+ // be many.
ld, ldRE = remoteexec.StaticRules(pctx, "ld",
blueprint.RuleParams{
Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " +
@@ -76,6 +79,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
}, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitInputs", "implicitOutputs"})
+ // Rules for .o files to combine to other .o files, using ld partial linking.
partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
blueprint.RuleParams{
// Without -no-pie, clang 7.0 adds -pie to link Android files,
@@ -91,6 +95,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
}, []string{"ldCmd", "ldFlags"}, []string{"implicitInputs", "inCommaList", "implicitOutputs"})
+ // Rule to invoke `ar` with given cmd and flags, but no static library depenencies.
ar = pctx.AndroidStaticRule("ar",
blueprint.RuleParams{
Command: "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
@@ -100,6 +105,8 @@
},
"arCmd", "arFlags")
+ // Rule to invoke `ar` with given cmd, flags, and library dependencies. Generates a .a
+ // (archive) file from .o files.
arWithLibs = pctx.AndroidStaticRule("arWithLibs",
blueprint.RuleParams{
Command: "rm -f ${out} && $arCmd $arObjFlags $out @${out}.rsp && $arCmd $arLibFlags $out $arLibs",
@@ -109,12 +116,7 @@
},
"arCmd", "arObjFlags", "arObjs", "arLibFlags", "arLibs")
- darwinStrip = pctx.AndroidStaticRule("darwinStrip",
- blueprint.RuleParams{
- Command: "${config.MacStripPath} -u -r -o $out $in",
- CommandDeps: []string{"${config.MacStripPath}"},
- })
-
+ // Rule to run objcopy --prefix-symbols (to prefix all symbols in a file with a given string).
prefixSymbols = pctx.AndroidStaticRule("prefixSymbols",
blueprint.RuleParams{
Command: "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
@@ -125,6 +127,24 @@
_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
+ // Rule to invoke `strip` (to discard symbols and data from object files).
+ strip = pctx.AndroidStaticRule("strip",
+ blueprint.RuleParams{
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
+ Command: "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
+ CommandDeps: []string{"$stripPath", "$xzCmd"},
+ Pool: darwinStripPool,
+ },
+ "args", "crossCompile")
+
+ // Rule to invoke `strip` (to discard symbols and data from object files) on darwin architecture.
+ darwinStrip = pctx.AndroidStaticRule("darwinStrip",
+ blueprint.RuleParams{
+ Command: "${config.MacStripPath} -u -r -o $out $in",
+ CommandDeps: []string{"${config.MacStripPath}"},
+ })
+
// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
// file descriptors on darwin. Limit concurrent calls to 5 on darwin.
darwinStripPool = func() blueprint.Pool {
@@ -137,18 +157,9 @@
}
}()
- strip = pctx.AndroidStaticRule("strip",
- blueprint.RuleParams{
- Depfile: "${out}.d",
- Deps: blueprint.DepsGCC,
- Command: "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
- CommandDeps: []string{"$stripPath", "$xzCmd"},
- Pool: darwinStripPool,
- },
- "args", "crossCompile")
-
_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
+ // Rule to repack an archive (.a) file with a subset of object files.
archiveRepack = pctx.AndroidStaticRule("archiveRepack",
blueprint.RuleParams{
Depfile: "${out}.d",
@@ -158,6 +169,7 @@
},
"objects")
+ // Rule to create an empty file at a given path.
emptyFile = pctx.AndroidStaticRule("emptyFile",
blueprint.RuleParams{
Command: "rm -f $out && touch $out",
@@ -165,6 +177,7 @@
_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
+ // A rule for extracting a table of contents from a shared library (.so).
toc = pctx.AndroidStaticRule("toc",
blueprint.RuleParams{
Depfile: "${out}.d",
@@ -175,6 +188,7 @@
},
"crossCompile", "format")
+ // Rule for invoking clang-tidy (a clang-based linter).
clangTidy, clangTidyRE = remoteexec.StaticRules(pctx, "clangTidy",
blueprint.RuleParams{
Command: "rm -f $out && $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
@@ -193,6 +207,7 @@
_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
+ // Rule for invoking yasm to compile .asm assembly files.
yasm = pctx.AndroidStaticRule("yasm",
blueprint.RuleParams{
Command: "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d",
@@ -202,6 +217,7 @@
},
"asFlags")
+ // Rule to invoke windres, for interaction with Windows resources.
windres = pctx.AndroidStaticRule("windres",
blueprint.RuleParams{
Command: "$windresCmd $flags -I$$(dirname $in) -i $in -o $out --preprocessor \"${config.ClangBin}/clang -E -xc-header -DRC_INVOKED\"",
@@ -220,13 +236,15 @@
Labels: map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
ExecStrategy: "${config.REAbiDumperExecStrategy}",
Platform: map[string]string{
- remoteexec.PoolKey: "${config.RECXXPool}",
+ remoteexec.PoolKey: "${config.RECXXPool}",
},
}, []string{"cFlags", "exportDirs"}, nil)
_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
_ = pctx.SourcePathVariable("sAbiLinkerLibs", "prebuilts/clang-tools/${config.HostPrebuiltTag}/lib64")
+ // Rule to combine .dump sAbi dump files from multiple source files into a single .ldump
+ // sAbi dump file.
sAbiLink, sAbiLinkRE = remoteexec.StaticRules(pctx, "sAbiLink",
blueprint.RuleParams{
Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ",
@@ -245,6 +263,7 @@
_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
+ // Rule to compare linked sAbi dump files (.ldump).
sAbiDiff = pctx.RuleFunc("sAbiDiff",
func(ctx android.PackageRuleContext) blueprint.RuleParams {
commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
@@ -258,11 +277,13 @@
},
"extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
+ // Rule to unzip a reference abi dump.
unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
blueprint.RuleParams{
Command: "gunzip -c $in > $out",
})
+ // Rule to zip files.
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
Command: "${SoongZipCmd} -o ${out} -C $$OUT_DIR -r ${out}.rsp",
@@ -278,6 +299,8 @@
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
_ = pctx.VariableFunc("kytheCuEncoding",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
+
+ // Rule to use kythe extractors to generate .kzip files, used to build code cross references.
kytheExtract = pctx.StaticRule("kythe",
blueprint.RuleParams{
Command: `rm -f $out && ` +
@@ -310,7 +333,11 @@
pctx.Import("android/soong/remoteexec")
}
+// builderFlags contains various types of command line flags (and settings) for use in building
+// build statements related to C++.
type builderFlags struct {
+ // Global flags (which build system or toolchain is responsible for). These are separate from
+ // local flags because they should appear first (so that they may be overridden by local flags).
globalCommonFlags string
globalAsFlags string
globalYasmFlags string
@@ -321,6 +348,7 @@
globalCppFlags string
globalLdFlags string
+ // Local flags (which individual modules are responsible for). These may override global flags.
localCommonFlags string
localAsFlags string
localYasmFlags string
@@ -331,32 +359,37 @@
localCppFlags string
localLdFlags string
- libFlags string
- extraLibFlags string
- tidyFlags string
- sAbiFlags string
- aidlFlags string
- rsFlags string
+ libFlags string // Flags to add to the linker directly after specifying libraries to link.
+ extraLibFlags string // Flags to add to the linker last.
+ tidyFlags string // Flags that apply to clang-tidy
+ sAbiFlags string // Flags that apply to header-abi-dumps
+ aidlFlags string // Flags that apply to aidl source files
+ rsFlags string // Flags that apply to renderscript source files
toolchain config.Toolchain
- tidy bool
- gcovCoverage bool
- sAbiDump bool
- emitXrefs bool
- assemblerWithCpp bool
+ // True if these extra features are enabled.
+ tidy bool
+ gcovCoverage bool
+ sAbiDump bool
+ emitXrefs bool
+
+ assemblerWithCpp bool // True if .s files should be processed with the c preprocessor.
systemIncludeFlags string
+ // True if static libraries should be grouped (using `-Wl,--start-group` and `-Wl,--end-group`).
groupStaticLibs bool
proto android.ProtoFlags
- protoC bool
- protoOptionsFile bool
+ protoC bool // If true, compile protos as `.c` files. Otherwise, output as `.cc`.
+ protoOptionsFile bool // If true, output a proto options file.
yacc *YaccProperties
lex *LexProperties
}
+// StripFlags represents flags related to stripping. This is separate from builderFlags, as these
+// flags are useful outside of this package (such as for Rust).
type StripFlags struct {
Toolchain config.Toolchain
StripKeepSymbols bool
@@ -367,6 +400,7 @@
StripUseGnuStrip bool
}
+// Objects is a collection of file paths corresponding to outputs for C++ related build statements.
type Objects struct {
objFiles android.Paths
tidyFiles android.Paths
@@ -396,9 +430,10 @@
}
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
-func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths,
+func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths,
flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
+ // Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
objFiles := make(android.Paths, len(srcFiles))
var tidyFiles android.Paths
if flags.tidy {
@@ -468,6 +503,7 @@
objFiles[i] = objFile
+ // Register compilation build statements. The actual rule used depends on the source file type.
switch srcFile.Ext() {
case ".asm":
ctx.Build(pctx, android.BuildParams{
@@ -562,6 +598,7 @@
},
})
+ // Register post-process build statements (such as for tidy or kythe).
if emitXref {
kytheFile := android.ObjPathWithExt(ctx, subdir, srcFile, "kzip")
ctx.Build(pctx, android.BuildParams{
@@ -639,7 +676,7 @@
}
// Generate a rule for compiling multiple .o files to a static library (.a)
-func TransformObjToStaticLib(ctx android.ModuleContext,
+func transformObjToStaticLib(ctx android.ModuleContext,
objFiles android.Paths, wholeStaticLibs android.Paths,
flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
@@ -682,7 +719,7 @@
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
// and shared libraries, to a shared library (.so) or dynamic executable
-func TransformObjToDynamicBinary(ctx android.ModuleContext,
+func transformObjToDynamicBinary(ctx android.ModuleContext,
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath, implicitOutputs android.WritablePaths) {
@@ -763,7 +800,7 @@
// Generate a rule to combine .dump sAbi dump files from multiple source files
// into a single .ldump sAbi dump file
-func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
+func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath {
@@ -810,7 +847,8 @@
return android.OptionalPathForPath(outputFile)
}
-func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
+// unzipRefDump registers a build statement to unzip a reference abi dump.
+func unzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
ctx.Build(pctx, android.BuildParams{
Rule: unzipRefSAbiDump,
@@ -821,7 +859,8 @@
return outputFile
}
-func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
+// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.ldump).
+func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
baseName, exportedHeaderFlags string, checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
@@ -872,7 +911,7 @@
}
// Generate a rule for extracting a table of contents from a shared library (.so)
-func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
+func transformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath, flags builderFlags) {
var format string
@@ -901,7 +940,7 @@
}
// Generate a rule for compiling multiple .o files to a .o using ld partial linking
-func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
+func transformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
ldCmd := "${config.ClangBin}/clang++"
@@ -926,8 +965,8 @@
})
}
-// Generate a rule for runing objcopy --prefix-symbols on a binary
-func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
+// Generate a rule for running objcopy --prefix-symbols on a binary
+func transformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
flags builderFlags, outputFile android.WritablePath) {
objcopyCmd := gccCmd(flags.toolchain, "objcopy")
@@ -944,7 +983,8 @@
})
}
-func TransformStrip(ctx android.ModuleContext, inputFile android.Path,
+// Registers a build statement to invoke `strip` (to discard symbols and data from object files).
+func transformStrip(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath, flags StripFlags) {
crossCompile := gccCmd(flags.Toolchain, "")
@@ -980,7 +1020,8 @@
})
}
-func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
+// Registers build statement to invoke `strip` on darwin architecture.
+func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath) {
ctx.Build(pctx, android.BuildParams{
@@ -991,7 +1032,8 @@
})
}
-func TransformCoverageFilesToZip(ctx android.ModuleContext,
+// Registers build statement to zip one or more coverage files.
+func transformCoverageFilesToZip(ctx android.ModuleContext,
inputs Objects, baseName string) android.OptionalPath {
if len(inputs.coverageFiles) > 0 {
@@ -1010,7 +1052,8 @@
return android.OptionalPath{}
}
-func TransformArchiveRepack(ctx android.ModuleContext, inputFile android.Path,
+// Rule to repack an archive (.a) file with a subset of object files.
+func transformArchiveRepack(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath, objects []string) {
ctx.Build(pctx, android.BuildParams{
@@ -1027,33 +1070,3 @@
func gccCmd(toolchain config.Toolchain, cmd string) string {
return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
}
-
-func splitListForSize(list android.Paths, limit int) (lists []android.Paths, err error) {
- var i int
-
- start := 0
- bytes := 0
- for i = range list {
- l := len(list[i].String())
- if l > limit {
- return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
- }
- if bytes+l > limit {
- lists = append(lists, list[start:i])
- start = i
- bytes = 0
- }
- bytes += l + 1 // count a space between each list element
- }
-
- lists = append(lists, list[start:])
-
- totalLen := 0
- for _, l := range lists {
- totalLen += len(l)
- }
- if totalLen != len(list) {
- panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
- }
- return lists, nil
-}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7c98585..af9b943 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2913,114 +2913,6 @@
}
}
-var (
- str11 = "01234567891"
- str10 = str11[:10]
- str9 = str11[:9]
- str5 = str11[:5]
- str4 = str11[:4]
-)
-
-var splitListForSizeTestCases = []struct {
- in []string
- out [][]string
- size int
-}{
- {
- in: []string{str10},
- out: [][]string{{str10}},
- size: 10,
- },
- {
- in: []string{str9},
- out: [][]string{{str9}},
- size: 10,
- },
- {
- in: []string{str5},
- out: [][]string{{str5}},
- size: 10,
- },
- {
- in: []string{str11},
- out: nil,
- size: 10,
- },
- {
- in: []string{str10, str10},
- out: [][]string{{str10}, {str10}},
- size: 10,
- },
- {
- in: []string{str9, str10},
- out: [][]string{{str9}, {str10}},
- size: 10,
- },
- {
- in: []string{str10, str9},
- out: [][]string{{str10}, {str9}},
- size: 10,
- },
- {
- in: []string{str5, str4},
- out: [][]string{{str5, str4}},
- size: 10,
- },
- {
- in: []string{str5, str4, str5},
- out: [][]string{{str5, str4}, {str5}},
- size: 10,
- },
- {
- in: []string{str5, str4, str5, str4},
- out: [][]string{{str5, str4}, {str5, str4}},
- size: 10,
- },
- {
- in: []string{str5, str4, str5, str5},
- out: [][]string{{str5, str4}, {str5}, {str5}},
- size: 10,
- },
- {
- in: []string{str5, str5, str5, str4},
- out: [][]string{{str5}, {str5}, {str5, str4}},
- size: 10,
- },
- {
- in: []string{str9, str11},
- out: nil,
- size: 10,
- },
- {
- in: []string{str11, str9},
- out: nil,
- size: 10,
- },
-}
-
-func TestSplitListForSize(t *testing.T) {
- for _, testCase := range splitListForSizeTestCases {
- out, _ := splitListForSize(android.PathsForTesting(testCase.in...), testCase.size)
-
- var outStrings [][]string
-
- if len(out) > 0 {
- outStrings = make([][]string, len(out))
- for i, o := range out {
- outStrings[i] = o.Strings()
- }
- }
-
- if !reflect.DeepEqual(outStrings, testCase.out) {
- t.Errorf("incorrect output:")
- t.Errorf(" input: %#v", testCase.in)
- t.Errorf(" size: %d", testCase.size)
- t.Errorf(" expected: %#v", testCase.out)
- t.Errorf(" got: %#v", outStrings)
- }
- }
-}
-
var staticLinkDepOrderTestCases = []struct {
// This is a string representation of a map[moduleName][]moduleDependency .
// It models the dependencies declared in an Android.bp file.
diff --git a/cc/compiler.go b/cc/compiler.go
index 04ed80d..f71dcca 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -649,7 +649,7 @@
func compileObjs(ctx android.ModuleContext, flags builderFlags,
subdir string, srcFiles, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
- return TransformSourceToObj(ctx, subdir, srcFiles, flags, pathDeps, cFlagsDeps)
+ return transformSourceToObj(ctx, subdir, srcFiles, flags, pathDeps, cFlagsDeps)
}
var thirdPartyDirPrefixExceptions = []*regexp.Regexp{
diff --git a/cc/library.go b/cc/library.go
index 7ae75f2..ddc7ff7 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -897,9 +897,9 @@
}
}
- TransformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, objs.tidyFiles)
+ transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, objs.tidyFiles)
- library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
+ library.coverageOutputFile = transformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
ctx.CheckbuildFile(outputFile)
@@ -974,7 +974,7 @@
// depending on a table of contents file instead of the library itself.
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
library.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
+ transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
stripFlags := flagsToStripFlags(flags)
if library.stripper.NeedsStrip(ctx) {
@@ -1019,7 +1019,7 @@
if Bool(library.Properties.Sort_bss_symbols_by_size) {
unsortedOutputFile := android.PathForModuleOut(ctx, "unsorted", fileName)
- TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
+ transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, unsortedOutputFile, implicitOutputs)
@@ -1029,7 +1029,7 @@
linkerDeps = append(linkerDeps, symbolOrderingFile)
}
- TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
+ transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs)
@@ -1039,7 +1039,7 @@
objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...)
objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
- library.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
+ library.coverageOutputFile = transformCoverageFilesToZip(ctx, objs, library.getLibName(ctx))
library.linkSAbiDumpFiles(ctx, objs, fileName, unstrippedOutputFile)
var staticAnalogue *StaticLibraryInfo
@@ -1115,7 +1115,7 @@
return refAbiDumpTextFile.Path()
}
if refAbiDumpGzipFile.Valid() {
- return UnzipRefDump(ctx, refAbiDumpGzipFile.Path(), fileName)
+ return unzipRefDump(ctx, refAbiDumpGzipFile.Path(), fileName)
}
return nil
}
@@ -1141,7 +1141,7 @@
SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
}
exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
- library.sAbiOutputFile = TransformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
+ library.sAbiOutputFile = transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
library.Properties.Header_abi_checker.Exclude_symbol_versions,
library.Properties.Header_abi_checker.Exclude_symbol_tags)
@@ -1150,7 +1150,7 @@
refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
if refAbiDumpFile != nil {
- library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
+ library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
refAbiDumpFile, fileName, exportedHeaderFlags,
Bool(library.Properties.Header_abi_checker.Check_all_apis),
ctx.isLlndk(ctx.Config()), ctx.isNdk(ctx.Config()), ctx.isVndkExt())
diff --git a/cc/object.go b/cc/object.go
index ab2672b..3ce7676 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -124,7 +124,7 @@
if String(object.Properties.Prefix_symbols) != "" {
output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
- TransformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile,
+ transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile,
builderFlags, output)
outputFile = output
}
@@ -134,12 +134,12 @@
if String(object.Properties.Prefix_symbols) != "" {
input := android.PathForModuleOut(ctx, "unprefixed", ctx.ModuleName()+objectExtension)
- TransformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
+ transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
builderFlags, output)
output = input
}
- TransformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps)
+ transformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps)
}
ctx.CheckbuildFile(outputFile)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 8873883..37df4ba 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -146,7 +146,7 @@
// depending on a table of contents file instead of the library itself.
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
+ transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
if ctx.Windows() && p.properties.Windows_import_lib != nil {
// Consumers of this library actually links to the import library in build
diff --git a/cc/strip.go b/cc/strip.go
index e9aec91..1f10a74 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -54,7 +54,7 @@
func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
flags StripFlags, isStaticLib bool) {
if actx.Darwin() {
- TransformDarwinStrip(actx, in, out)
+ transformDarwinStrip(actx, in, out)
} else {
if Bool(stripper.StripProperties.Strip.Keep_symbols) {
flags.StripKeepSymbols = true
@@ -68,7 +68,7 @@
if actx.Config().Debuggable() && !flags.StripKeepMiniDebugInfo && !isStaticLib {
flags.StripAddGnuDebuglink = true
}
- TransformStrip(actx, in, out, flags)
+ transformStrip(actx, in, out, flags)
}
}
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 0c934ad..bda73ea 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -90,7 +90,7 @@
if library.Properties.Repack_objects_to_keep != nil {
fileName := ctx.ModuleName() + staticLibraryExtension
repackedPath := android.PathForModuleOut(ctx, fileName)
- TransformArchiveRepack(ctx, outputFile, repackedPath, library.Properties.Repack_objects_to_keep)
+ transformArchiveRepack(ctx, outputFile, repackedPath, library.Properties.Repack_objects_to_keep)
outputFile = repackedPath
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 6563f6e..94f859e 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -339,7 +339,7 @@
// depending on a table of contents file instead of the library itself.
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+ transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: in,
diff --git a/cc/vndk.go b/cc/vndk.go
index 4a005f3..fcaf3af 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -727,7 +727,7 @@
var txtBuilder strings.Builder
for idx, k := range android.SortedStringKeys(m) {
if idx > 0 {
- txtBuilder.WriteString("\\n")
+ txtBuilder.WriteString("\n")
}
txtBuilder.WriteString(k)
txtBuilder.WriteString(" ")
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index c0320eb..e6e2ad8 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -154,7 +154,7 @@
// depending on a table of contents file instead of the library itself.
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+ transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
p.androidMkSuffix = p.NameSuffix()
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index b88803a..d758de2 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -79,7 +79,7 @@
srcDir := filepath.Dir(flag.Arg(0))
var ctx *android.Context
configuration := newConfig(srcDir)
- extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
+ extraNinjaDeps := []string{configuration.ProductVariablesFileName}
// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
// and soong_build will rerun when it is set for the first time.
diff --git a/java/aapt2.go b/java/aapt2.go
index 04e4de5..5346ddf 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -25,12 +25,9 @@
"android/soong/android"
)
-const AAPT2_SHARD_SIZE = 100
-
// Convert input resource file path to output file path.
// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
-// For other resource file, just replace the last "/" with "_" and
-// add .flat extension.
+// For other resource file, just replace the last "/" with "_" and add .flat extension.
func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
name := res.Base()
@@ -43,6 +40,7 @@
return android.PathForModuleOut(ctx, "aapt2", subDir, name)
}
+// pathsToAapt2Paths Calls pathToAapt2Path on each entry of the given Paths, i.e. []Path.
func pathsToAapt2Paths(ctx android.ModuleContext, resPaths android.Paths) android.WritablePaths {
outPaths := make(android.WritablePaths, len(resPaths))
@@ -53,6 +51,9 @@
return outPaths
}
+// Shard resource files for efficiency. See aapt2Compile for details.
+const AAPT2_SHARD_SIZE = 100
+
var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile",
blueprint.RuleParams{
Command: `${config.Aapt2Cmd} compile -o $outDir $cFlags $in`,
@@ -60,14 +61,26 @@
},
"outDir", "cFlags")
+// aapt2Compile compiles resources and puts the results in the requested directory.
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
flags []string) android.WritablePaths {
+ // Shard the input paths so that they can be processed in parallel. If we shard them into too
+ // small chunks, the additional cost of spinning up aapt2 outweighs the performance gain. The
+ // current shard size, 100, seems to be a good balance between the added cost and the gain.
+ // The aapt2 compile actions are trivially short, but each action in ninja takes on the order of
+ // ~10 ms to run. frameworks/base/core/res/res has >10k resource files, so compiling each one
+ // with an individual action could take 100 CPU seconds. Sharding them reduces the overhead of
+ // starting actions by a factor of 100, at the expense of recompiling more files when one
+ // changes. Since the individual compiles are trivial it's a good tradeoff.
shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE)
ret := make(android.WritablePaths, 0, len(paths))
for i, shard := range shards {
+ // This should be kept in sync with pathToAapt2Path. The aapt2 compile command takes an
+ // output directory path, but not output file paths. So, outPaths is just where we expect
+ // the output files will be located.
outPaths := pathsToAapt2Paths(ctx, shard)
ret = append(ret, outPaths...)
@@ -82,6 +95,12 @@
Inputs: shard,
Outputs: outPaths,
Args: map[string]string{
+ // The aapt2 compile command takes an output directory path, but not output file paths.
+ // outPaths specified above is only used for dependency management purposes. In order for
+ // the outPaths values to match the actual outputs from aapt2, the dir parameter value
+ // must be a common prefix path of the paths values, and the top-level path segment used
+ // below, "aapt2", must always be kept in sync with the one in pathToAapt2Path.
+ // TODO(b/174505750): Make this easier and robust to use.
"outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
"cFlags": strings.Join(flags, " "),
},
@@ -104,6 +123,8 @@
},
}, "cFlags", "resZipDir", "zipSyncFlags")
+// Unzips the given compressed file and compiles the resource source files in it. The zipPrefix
+// parameter points to the subdirectory in the zip file where the resource files are located.
func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string,
flags []string) {
@@ -163,6 +184,7 @@
var inFlags []string
if len(compiledRes) > 0 {
+ // Create a file that contains the list of all compiled resource file paths.
resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list")
// Write out file lists to files
ctx.Build(pctx, android.BuildParams{
@@ -174,10 +196,12 @@
deps = append(deps, compiledRes...)
deps = append(deps, resFileList)
+ // aapt2 filepath arguments that start with "@" mean file-list files.
inFlags = append(inFlags, "@"+resFileList.String())
}
if len(compiledOverlay) > 0 {
+ // Compiled overlay files are processed the same way as compiled resources.
overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list")
ctx.Build(pctx, android.BuildParams{
Rule: fileListToFileRule,
@@ -188,9 +212,11 @@
deps = append(deps, compiledOverlay...)
deps = append(deps, overlayFileList)
+ // Compiled overlay files are passed over to aapt2 using -R option.
inFlags = append(inFlags, "-R", "@"+overlayFileList.String())
}
+ // Set auxiliary outputs as implicit outputs to establish correct dependency chains.
implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
linkOutput := packageRes
@@ -212,6 +238,10 @@
Implicits: deps,
Output: linkOutput,
ImplicitOutputs: implicitOutputs,
+ // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
+ // values via the flags parameter when it wants to split outputs.
+ // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
+ // tidy.
Args: map[string]string{
"flags": strings.Join(flags, " "),
"inFlags": strings.Join(inFlags, " "),
@@ -230,6 +260,8 @@
CommandDeps: []string{"${config.Aapt2Cmd}"},
})
+// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto
+// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,