Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/java/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 11 kB image not shown  

Impressum classpath_fragment.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java

import (
 "fmt"
 "strings"

 "github.com/google/blueprint"
 "github.com/google/blueprint/proptools"

 "android/soong/android"
)

//go:generate go run ../../blueprint/gobtools/codegen

// Build rules and utilities to generate individual packages/modules/common/proto/classpaths.proto
// config files based on build configuration to embed into /system and /apex on a device.
//
// See `derive_classpath` service that reads the configs at runtime and defines *CLASSPATH variables
// on the device.

type classpathType int

const (
 // Matches definition in packages/modules/common/proto/classpaths.proto
 BOOTCLASSPATH classpathType = iota
 DEX2OATBOOTCLASSPATH
 SYSTEMSERVERCLASSPATH
 STANDALONE_SYSTEMSERVER_JARS
)

func (c classpathType) String() string {
 return [...]string{"BOOTCLASSPATH", "DEX2OATBOOTCLASSPATH", "SYSTEMSERVERCLASSPATH", "STANDALONE_SYSTEMSERVER_JARS"}[c]
}

type classpathFragmentProperties struct {
 // Whether to generated classpaths.proto config instance for the fragment. If the config is not
 // generated, then relevant boot jars are added to platform classpath, i.e. platform_bootclasspath
 // or platform_systemserverclasspath. This is useful for non-updatable APEX boot jars, to keep
 // them as part of dexopt on device. Defaults to true.
 Generate_classpaths_proto *bool

 // If not blank, the minimum SDK version that the fragment will be included in. This is mostly
 // relevant when other fragments depend on this one through the `fragments` property, to prune
 // those dependencies in SDKs where this fragment doesn't exist.
 Min_sdk_version proptools.Configurable[string] `android:"replace_instead_of_append"`
}

// classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH
// variables at runtime.
type classpathFragment interface {
 android.Module

 classpathFragmentBase() *ClasspathFragmentBase

 // MinSdkVersion returns the value of the min_sdk_version property.
 MinSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel

 // ConfigurableEvaluator returns the ConfigurableEvaluator for the module.
 ConfigurableEvaluator(ctx android.ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator
}

// ClasspathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
// such modules are expected to call initClasspathFragment().
type ClasspathFragmentBase struct {
 android.ModuleBase

 properties classpathFragmentProperties

 classpathType classpathType

 outputFilepath android.OutputPath
 installDirPath android.InstallPath
}

func (c *ClasspathFragmentBase) classpathFragmentBase() *ClasspathFragmentBase {
 return c
}

func (c *ClasspathFragmentBase) MinSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
 minSdkVersion := c.properties.Min_sdk_version.Get(c.ConfigurableEvaluator(ctx))
 if minSdkVersion.IsPresent() {
  return android.ApiLevelFrom(ctx, minSdkVersion.Get())
 }
 return android.MinApiLevel
}

func (c *ClasspathFragmentBase) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
 // Return MinApiLevel since fragments should be allowed to have newer min_sdk_version's than their
 // APEX'es because they may be added to existing modules to add classpath jars on newer platform
 // releases.
 return android.MinApiLevel
}

func (c *ClasspathFragmentBase) checkMinSdkVersionConstraint(ctx android.ModuleContext) {
 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 if !apexInfo.IsForPlatform() && !apexInfo.MinSdkVersion.IsCurrent() {
  fragmentMinSdk := c.properties.Min_sdk_version.Get(c.ConfigurableEvaluator(ctx))
  if fragmentMinSdk.IsPresent() {
   apiLevel := android.ApiLevelFrom(ctx, fragmentMinSdk.Get())
   if apiLevel.LessThan(apexInfo.MinSdkVersion) {
    ctx.ModuleErrorf("fragment min_sdk_version %v lower than its APEX (%v)", apiLevel, apexInfo.MinSdkVersion)
   }
  }
 }
}

// Initializes ClasspathFragmentBase struct. Must be called by all modules that include ClasspathFragmentBase.
func initClasspathFragment(c classpathFragment, classpathType classpathType) {
 base := c.classpathFragmentBase()
 base.classpathType = classpathType
 c.AddProperties(&base.properties)
}

// Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto
type classpathJar struct {
 path          string
 classpath     classpathType
 minSdkVersion string
 maxSdkVersion string
}

// gatherPossibleApexModuleNamesAndStems returns a set of module and stem names from the
// supplied contents that may be in the apex boot jars.
//
// The module names are included because sometimes the stem is set to just change the name of
// the installed file and it expects the configuration to still use the actual module name.
//
// The stem names are included because sometimes the stem is set to change the effective name of the
// module that is used in the configuration as well,e .g. when a test library is overriding an
// actual boot jar
func gatherPossibleApexModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string {
 set := map[string]struct{}{}
 for _, name := range contents {
  dep := ctx.GetDirectDepProxyWithTag(name, tag)
  if dep.IsNil() && ctx.Config().AllowMissingDependencies() {
   // Ignore apex boot jars from dexpreopt if it does not exist, and missing deps are allowed.
   continue
  }
  info := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider)
  set[ModuleStemForDeapexing(ctx, dep)] = struct{}{}
  set[info.Stem] = struct{}{}
 }
 return android.SortedKeys(set)
}

// Converts android.ConfiguredJarList into a list of classpathJars for each given classpathType.
func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, classpaths ...classpathType) []classpathJar {
 paths := configuredJars.DevicePaths(ctx.Config(), android.Android)
 jars := make([]classpathJar, 0, len(paths)*len(classpaths))
 for i := 0; i < len(paths); i++ {
  for _, classpathType := range classpaths {
   jar := classpathJar{
    classpath: classpathType,
    path:      paths[i],
   }
   ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
    if m.Name() != configuredJars.Jar(i) {
     return
    }
    if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
     info := android.OtherModuleProviderOrDefault(ctx, m, JavaInfoProvider)
     commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
     minSdkVersion := *commonInfo.MinSdkVersion.ApiLevel
     maxSdkVersion := info.MaxSdkVersion
     // TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
     if minSdkVersion.Specified() {
      if minSdkVersion.IsCurrent() {
       jar.minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
      } else {
       jar.minSdkVersion = minSdkVersion.String()
      }
     }
     if maxSdkVersion.Specified() {
      if maxSdkVersion.IsCurrent() {
       jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
      } else {
       jar.maxSdkVersion = maxSdkVersion.String()
      }
     }
    }
   })
   jars = append(jars, jar)
  }
 }
 return jars
}

func (c *ClasspathFragmentBase) outputFilename() string {
 return strings.ToLower(c.classpathType.String()) + ".pb"
}

func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) android.OutputPath {
 generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true)
 if generateProto {
  outputFilename := c.outputFilename()
  c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
  c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")

  generatedTextproto := android.PathForModuleOut(ctx, outputFilename+".textproto")
  writeClasspathsTextproto(ctx, generatedTextproto, jars)

  rule := android.NewRuleBuilder(pctx, ctx).SandboxDisabled()
  rule.Command().
   BuiltTool("conv_classpaths_proto").
   Flag("encode").
   Flag("--format=textproto").
   FlagWithInput("--input=", generatedTextproto).
   FlagWithOutput("--output=", c.outputFilepath)

  rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
 }

 classpathProtoInfo := ClasspathFragmentProtoContentInfo{
  ClasspathFragmentProtoGenerated:  generateProto,
  ClasspathFragmentProtoContents:   configuredJars,
  ClasspathFragmentProtoInstallDir: c.installDirPath,
  ClasspathFragmentProtoOutput:     c.outputFilepath,
 }
 android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
 return c.outputFilepath
}

func (c *ClasspathFragmentBase) installClasspathProto(ctx android.ModuleContext) android.InstallPath {
 return ctx.InstallFile(c.installDirPath, c.outputFilename(), c.outputFilepath)
}

func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
 var content strings.Builder

 for _, jar := range jars {
  fmt.Fprintf(&content, "jars {\n")
  fmt.Fprintf(&content, "path: \"%s\"\n", jar.path)
  fmt.Fprintf(&content, "classpath: %s\n", jar.classpath)
  fmt.Fprintf(&content, "min_sdk_version: \"%s\"\n", jar.minSdkVersion)
  fmt.Fprintf(&content, "max_sdk_version: \"%s\"\n", jar.maxSdkVersion)
  fmt.Fprintf(&content, "}\n")
 }

 android.WriteFileRule(ctx, output, content.String())
}

// Returns AndroidMkInfo objects to install generated classpath.proto.
// Do not use this to install into APEXes as the injection of the generated files happen separately for APEXes.
func (c *ClasspathFragmentBase) androidMkInfo() android.AndroidMkInfo {
 info := android.AndroidMkInfo{
  Class:      "ETC",
  OutputFile: android.OptionalPathForPath(c.outputFilepath),
 }
 info.SetString("LOCAL_MODULE_PATH", c.installDirPath.String())
 info.SetString("LOCAL_INSTALLED_MODULE_STEM", c.outputFilepath.Base())
 return info
}

var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider[ClasspathFragmentProtoContentInfo]()

// @auto-generate: gob
type ClasspathFragmentProtoContentInfo struct {
 // Whether the classpaths.proto config is generated for the fragment.
 ClasspathFragmentProtoGenerated bool

 // ClasspathFragmentProtoContents contains a list of jars that are part of this classpath fragment.
 ClasspathFragmentProtoContents android.ConfiguredJarList

 // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
 //
 // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir
 // for more details.
 ClasspathFragmentProtoOutput android.OutputPath

 // ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file.
 //
 // The path encodes expected sub-location within partitions, i.e. etc/classpaths/<proto-file>,
 // for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path
 // use android.InstallPath#Rel().
 //
 // This is only relevant for APEX modules as they perform their own installation; while regular
 // system files are installed via ClasspathFragmentBase#androidMkInfo().
 ClasspathFragmentProtoInstallDir android.InstallPath
}

[Seitenstruktur0.27Druckenetwas mehr zur Ethik2026-06-28]