diff options
author | 2025-03-18 02:55:44 -0700 | |
---|---|---|
committer | 2025-03-18 02:55:44 -0700 | |
commit | 6fc7cbe2597a93d152404e1706d1bd10bf33075d (patch) | |
tree | de7d9e4e4abbd3a8d953dcb108940abfb7612cb9 /android/config.go | |
parent | d0bde424e3119c0ad0ff8879786d2cc1febe1dfa (diff) | |
parent | d648ee443516cc45f349c9a8322550cf375f7eec (diff) |
Generic configuration for generic system modules. am: be6f81d61e am: d648ee4435
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/3425639
Change-Id: Ibd30d3911934db8857cf84de75200207a2a7331c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'android/config.go')
-rw-r--r-- | android/config.go | 158 |
1 files changed, 125 insertions, 33 deletions
diff --git a/android/config.go b/android/config.go index 98a408b60..637625dbe 100644 --- a/android/config.go +++ b/android/config.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "runtime" "strconv" "strings" @@ -108,6 +109,10 @@ const ( const testKeyDir = "build/make/target/product/security" +func (c Config) genericConfig() Config { + return Config{c.config.genericConfig} +} + // SoongOutDir returns the build output directory for the configuration. func (c Config) SoongOutDir() string { return c.soongOutDir @@ -372,7 +377,7 @@ type config struct { // regenerate build.ninja. ninjaFileDepsSet sync.Map - OncePer + *OncePer // If buildFromSourceStub is true then the Java API stubs are // built from the source Java files, not the signature text files. @@ -382,6 +387,17 @@ type config struct { // modules that aren't mixed-built for at least one variant will cause a build // failure ensureAllowlistIntegrity bool + + // If isGeneric is true, this config is the generic config. + isGeneric bool + + // InstallPath requires the device name. + // This is only for the installPath. + deviceNameToInstall *string + + // Copy of this config struct but some product-specific variables are + // replaced with the generic configuration values. + genericConfig *config } type partialCompileFlags struct { @@ -639,11 +655,9 @@ func NullConfig(outDir, soongOutDir string) Config { } } -// NewConfig creates a new Config object. The srcDir argument specifies the path -// to the root source directory. It also loads the config file, if found. -func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) { +func initConfig(cmdArgs CmdArgs, availableEnv map[string]string) (*config, error) { // Make a config with default options. - config := &config{ + newConfig := &config{ ProductVariablesFileName: cmdArgs.SoongVariables, env: availableEnv, @@ -657,70 +671,72 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) moduleListFile: cmdArgs.ModuleListFile, fs: pathtools.NewOsFs(absSrcDir), + OncePer: &OncePer{}, + buildFromSourceStub: cmdArgs.BuildFromSourceStub, } variant, ok := os.LookupEnv("TARGET_BUILD_VARIANT") isEngBuild := !ok || variant == "eng" - config.deviceConfig = &deviceConfig{ - config: config, + newConfig.deviceConfig = &deviceConfig{ + config: newConfig, } // Soundness check of the build and source directories. This won't catch strange // configurations with symlinks, but at least checks the obvious case. absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir) if err != nil { - return Config{}, err + return &config{}, err } absSrcDir, err := filepath.Abs(".") if err != nil { - return Config{}, err + return &config{}, err } if strings.HasPrefix(absSrcDir, absBuildDir) { - return Config{}, fmt.Errorf("Build dir must not contain source directory") + return &config{}, fmt.Errorf("Build dir must not contain source directory") } // Load any configurable options from the configuration file - err = loadConfig(config) + err = loadConfig(newConfig) if err != nil { - return Config{}, err + return &config{}, err } KatiEnabledMarkerFile := filepath.Join(cmdArgs.SoongOutDir, ".soong.kati_enabled") if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil { - config.katiEnabled = true + newConfig.katiEnabled = true } - determineBuildOS(config) + determineBuildOS(newConfig) // Sets up the map of target OSes to the finer grained compilation targets // that are configured from the product variables. - targets, err := decodeTargetProductVariables(config) + targets, err := decodeTargetProductVariables(newConfig) if err != nil { - return Config{}, err + return &config{}, err } - config.partialCompileFlags, err = config.parsePartialCompileFlags(isEngBuild) + newConfig.partialCompileFlags, err = newConfig.parsePartialCompileFlags(isEngBuild) if err != nil { - return Config{}, err + return &config{}, err } // Make the CommonOS OsType available for all products. targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]} var archConfig []archConfig - if config.NdkAbis() { + if newConfig.NdkAbis() { archConfig = getNdkAbisConfig() - } else if config.AmlAbis() { + } else if newConfig.AmlAbis() { archConfig = getAmlAbisConfig() } if archConfig != nil { androidTargets, err := decodeAndroidArchSettings(archConfig) if err != nil { - return Config{}, err + return &config{}, err } targets[Android] = androidTargets } @@ -728,37 +744,113 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) multilib := make(map[string]bool) for _, target := range targets[Android] { if seen := multilib[target.Arch.ArchType.Multilib]; seen { - config.multilibConflicts[target.Arch.ArchType] = true + newConfig.multilibConflicts[target.Arch.ArchType] = true } multilib[target.Arch.ArchType.Multilib] = true } // Map of OS to compilation targets. - config.Targets = targets + newConfig.Targets = targets // Compilation targets for host tools. - config.BuildOSTarget = config.Targets[config.BuildOS][0] - config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] + newConfig.BuildOSTarget = newConfig.Targets[newConfig.BuildOS][0] + newConfig.BuildOSCommonTarget = getCommonTargets(newConfig.Targets[newConfig.BuildOS])[0] // Compilation targets for Android. - if len(config.Targets[Android]) > 0 { - config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0] - config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0] + if len(newConfig.Targets[Android]) > 0 { + newConfig.AndroidCommonTarget = getCommonTargets(newConfig.Targets[Android])[0] + newConfig.AndroidFirstDeviceTarget = FirstTarget(newConfig.Targets[Android], "lib64", "lib32")[0] } setBuildMode := func(arg string, mode SoongBuildMode) { if arg != "" { - if config.BuildMode != AnalysisNoBazel { + if newConfig.BuildMode != AnalysisNoBazel { fmt.Fprintf(os.Stderr, "buildMode is already set, illegal argument: %s", arg) os.Exit(1) } - config.BuildMode = mode + newConfig.BuildMode = mode } } setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph) setBuildMode(cmdArgs.DocFile, GenerateDocFile) - config.productVariables.Build_from_text_stub = boolPtr(config.BuildFromTextStub()) + newConfig.productVariables.Build_from_text_stub = boolPtr(newConfig.BuildFromTextStub()) + + newConfig.deviceNameToInstall = newConfig.productVariables.DeviceName + + return newConfig, err +} + +// Replace variables in config.productVariables that have tags with "generic" key. +// A generic tag may have a string or an int value for the generic configuration. +// If the value is "unset", generic configuration will unset the variable. +func overrideGenericConfig(config *config) { + config.genericConfig.isGeneric = true + type_pv := reflect.TypeOf(config.genericConfig.productVariables) + value_pv := reflect.ValueOf(&config.genericConfig.productVariables) + for i := range type_pv.NumField() { + type_pv_field := type_pv.Field(i) + generic_value := type_pv_field.Tag.Get("generic") + // If a product variable has an annotation of "generic" tag, use the + // value of the tag to set the generic variable. + if generic_value != "" { + value_pv_field := value_pv.Elem().Field(i) + + if generic_value == "unset" { + // unset the product variable + value_pv_field.SetZero() + continue + } + + kind_of_type_pv := type_pv_field.Type.Kind() + is_pointer := false + if kind_of_type_pv == reflect.Pointer { + is_pointer = true + kind_of_type_pv = type_pv_field.Type.Elem().Kind() + } + + switch kind_of_type_pv { + case reflect.String: + if is_pointer { + value_pv_field.Set(reflect.ValueOf(stringPtr(generic_value))) + } else { + value_pv_field.Set(reflect.ValueOf(generic_value)) + } + case reflect.Int: + generic_int, err := strconv.Atoi(generic_value) + if err != nil { + panic(fmt.Errorf("Only an int value can be assigned to int variable: %s", err)) + } + if is_pointer { + value_pv_field.Set(reflect.ValueOf(intPtr(generic_int))) + } else { + value_pv_field.Set(reflect.ValueOf(generic_int)) + } + default: + panic(fmt.Errorf("Unknown type to replace for generic variable: %s", &kind_of_type_pv)) + } + } + } + + // OncePer must be a singleton. + config.genericConfig.OncePer = config.OncePer + // keep the device name to get the install path. + config.genericConfig.deviceNameToInstall = config.deviceNameToInstall +} + +// NewConfig creates a new Config object. It also loads the config file, if +// found. The Config object includes a duplicated Config object in it for the +// generic configuration that does not provide any product specific information. +func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) { + config, err := initConfig(cmdArgs, availableEnv) + if err != nil { + return Config{}, err + } + + // Initialize generic configuration. + config.genericConfig, err = initConfig(cmdArgs, availableEnv) + // Update product specific variables with the generic configuration. + overrideGenericConfig(config) return Config{config}, err } @@ -946,7 +1038,7 @@ func (c *config) DisplayBuildNumber() bool { // require them to run and get the current build fingerprint. This ensures they // don't rebuild on every incremental build when the build number changes. func (c *config) BuildFingerprintFile(ctx PathContext) Path { - return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildFingerprintFile)) + return PathForArbitraryOutput(ctx, "target", "product", *c.deviceNameToInstall, String(c.productVariables.BuildFingerprintFile)) } // BuildNumberFile returns the path to a text file containing metadata @@ -974,7 +1066,7 @@ func (c *config) BuildHostnameFile(ctx PathContext) Path { // require them to run and get the current build thumbprint. This ensures they // don't rebuild on every incremental build when the build thumbprint changes. func (c *config) BuildThumbprintFile(ctx PathContext) Path { - return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildThumbprintFile)) + return PathForArbitraryOutput(ctx, "target", "product", *c.deviceNameToInstall, String(c.productVariables.BuildThumbprintFile)) } // DeviceName returns the name of the current device target. |