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

Quelle  provider.go   Sprache: unbekannt

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

// Copyright 2020 Google Inc. All rights reserved.
//
// 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 blueprint

import (
 "fmt"

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

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

// This file implements Providers, modelled after Bazel
// (https://docs.bazel.build/versions/master/skylark/rules.html#providers).
// Each provider can be associated with a mutator, in which case the value for the provider for a
// module can only be set during the mutator call for the module, and the value can only be
// retrieved after the mutator call for the module. For providers not associated with a mutator, the
// value can for the provider for a module can only be set during GenerateBuildActions for the
// module, and the value can only be retrieved after GenerateBuildActions for the module.
//
// Providers are globally registered during init() and given a unique ID.  The value of a provider
// for a module is stored in an []any indexed by the ID.  If the value of a provider has
// not been set, the value in the []any will be nil.
//
// If the storage used by the provider value arrays becomes too large:
//  sizeof([]interface) * number of providers * number of modules that have a provider value set
// then the storage can be replaced with something like a bitwise trie.
//
// The purpose of providers is to provide a serializable checkpoint between modules to enable
// Blueprint to skip parts of the analysis phase when inputs haven't changed.  To that end,
// values passed to providers should be treated as immutable by callers to both the getters and
// setters.  Go doesn't provide any way to enforce immutability on arbitrary types, so it may be
// necessary for the getters and setters to make deep copies of the values, likely extending
// proptools.CloneProperties to do so.

const singletonTag = "singleton"

type typedProviderKey[K any] struct {
 providerKey
}

// @auto-generate: gob
type providerKey struct {
 id      int
 typ     string
 mutator string
}

func (p *providerKey) provider() *providerKey { return p }

type AnyProviderKey interface {
 provider() *providerKey
}
type ProviderKey[K any] struct {
 *typedProviderKey[K]
}

var _ AnyProviderKey = (*providerKey)(nil)
var _ AnyProviderKey = ProviderKey[bool]{}

var providerRegistry []*providerKey

// NewProvider returns a ProviderKey for the given type.
//
// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module
// inside GenerateBuildActions for the module, and to get the value from GenerateBuildActions from
// any module later in the build graph.
func NewProvider[K gobtools.CustomEnc]() ProviderKey[K] {
 return NewMutatorProvider[K]("")
}

// NewSingletonProvider returns a ProviderKey for the given type.
//
// The returned ProviderKey can be used to set a value of the ProviderKey's type for a singleton
// inside GenerateBuildActions for the singleton, and to get the value from GenerateBuildActions from
// any singleton later in the build graph.
func NewSingletonProvider[K any]() ProviderKey[K] {
 return NewMutatorProvider[K](singletonTag)
}

// NewMutatorProvider returns a ProviderKey for the given type.
//
// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module inside
// the given mutator for the module, and to get the value from GenerateBuildActions from any
// module later in the build graph in the same mutator, or any module in a later mutator or during
// GenerateBuildActions.
func NewMutatorProvider[K any](mutator string) ProviderKey[K] {
 checkCalledFromInit()

 typ := fmt.Sprintf("%T", *new(K))

 provider := ProviderKey[K]{
  typedProviderKey: &typedProviderKey[K]{
   providerKey: providerKey{
    id:      len(providerRegistry),
    typ:     typ,
    mutator: mutator,
   },
  },
 }

 providerRegistry = append(providerRegistry, &provider.providerKey)

 return provider
}

func ProviderType(id int) string {
 if id >= 0 && id < len(providerRegistry) {
  return providerRegistry[id].typ
 }
 return "unknown"
}

func ProviderMutator(id int) string {
 if id >= 0 && id < len(providerRegistry) {
  return providerRegistry[id].mutator
 }
 return "unknown"
}

// initProviders fills c.providerMutators with the *mutatorInfo associated with each provider ID,
// if any.
func (c *Context) initProviders() {
 c.providerMutators = make([]*mutatorInfo, len(providerRegistry))
 for _, provider := range providerRegistry {
  for _, mutator := range c.mutatorInfo {
   if mutator.name == provider.mutator {
    c.providerMutators[provider.id] = mutator
   }
  }
 }
}

// setProvider sets the value for a provider on a moduleInfo.  Verifies that it is called during the
// appropriate mutator or GenerateBuildActions pass for the provider, and that the value is of the
// appropriate type.  The value should not be modified after being passed to setProvider.
//
// Once Go has generics the value parameter can be typed:
// setProvider(type T)(m *moduleInfo, provider ProviderKey(T), value T)
func (c *Context) setProvider(m *moduleInfo, provider *providerKey, value any) {
 if m.incrementalRestored {
  if c.incrementalProviderTest {
   return
  }
  panic("shouldn't set provider after the module was restored from cache")
 }
 if provider.mutator == "" {
  if !m.startedGenerateBuildActions {
   panic(fmt.Sprintf("Can't set value of provider %s before GenerateBuildActions started",
    provider.typ))
  } else if m.finishedGenerateBuildActions {
   panic(fmt.Sprintf("Can't set value of provider %s after GenerateBuildActions finished",
    provider.typ))
  }
 } else {
  expectedMutator := c.providerMutators[provider.id]
  if expectedMutator == nil {
   panic(fmt.Sprintf("Can't set value of provider %s associated with unregistered mutator %s",
    provider.typ, provider.mutator))
  } else if c.mutatorFinishedForModule(expectedMutator, m) {
   panic(fmt.Sprintf("Can't set value of provider %s after mutator %s finished",
    provider.typ, provider.mutator))
  } else if !c.mutatorStartedForModule(expectedMutator, m) {
   panic(fmt.Sprintf("Can't set value of provider %s before mutator %s started",
    provider.typ, provider.mutator))
  }
 }

 c.setProviderInternal(&m.providerInfo, provider, value)
}

func (c *Context) setSingletonProvider(s *singletonInfo, provider *providerKey, value any) {
 if s.incrementalRestored {
  if c.incrementalProviderTest {
   return
  }
  panic("shouldn't set provider after the singleton was restored from cache")
 }
 if provider.mutator != singletonTag {
  panic(fmt.Sprintf("Can't set value of non-singleton provider %s inside singleton %s", provider.typ, s.name))
 } else {
  if !s.startedGenerateBuildActions {
   panic(fmt.Sprintf("Can't set value of provider %s before %s's GenerateBuildActions started",
    provider.typ, s.name))
  } else if s.finishedGenerateBuildActions {
   panic(fmt.Sprintf("Can't set value of provider %s after %s's GenerateBuildActions finished",
    provider.typ, s.name))
  }
 }
 c.setProviderInternal(&s.providerInfo, provider, value)
}

func (c *Context) setProviderInternal(info *providerInfo, provider *providerKey, value any) {
 if info.providers == nil {
  info.providers = make([]any, len(providerRegistry))
 }

 if info.providers[provider.id] != nil {
  panic(fmt.Sprintf("Value of provider %s is already set", provider.typ))
 }

 info.providers[provider.id] = value

 containsConfigurableChan := make(chan bool)
 go func() {
  containsConfigurableChan <- proptools.ContainsConfigurable(value)
 }()

 if info.providerInitialValueHashes == nil {
  info.providerInitialValueHashes = make([]proptools.Hash, len(providerRegistry))
 }
 hash, err := proptools.CalculateHashReflection(value)
 if err != nil {
  panic(fmt.Sprintf("Can't set value of provider %s: %s", provider.typ, err.Error()))
 }
 info.providerInitialValueHashes[provider.id] = hash

 if <-containsConfigurableChan {
  panic(fmt.Sprintf("Providers can't contain Configurable objects: %s", provider.typ))
 }
}

// provider returns the value, if any, for a given provider for a module.  Verifies that it is
// called after the appropriate mutator or GenerateBuildActions pass for the provider on the module.
// If the value for the provider was not set it returns nil.  The return value should always be considered read-only.
//
// Once Go has generics the return value can be typed and the type assert by callers can be dropped:
// provider(type T)(m *moduleInfo, provider ProviderKey(T)) T
func (c *Context) provider(m *moduleInfo, provider *providerKey) (any, bool) {
 validateProvider(c, m, provider)
 maybeRestoreProviders(c, &m.commonIncrementalInfo, provider)
 if len(m.providers) > provider.id {
  if p := m.providers[provider.id]; p != nil {
   return p, true
  }
 }

 return nil, false
}

func (c *Context) singletonProvider(s *singletonInfo, provider *providerKey) (any, bool) {
 validateSingletonProvider(s, provider)
 maybeRestoreProviders(c, &s.commonIncrementalInfo, provider)
 if len(s.providers) > provider.id {
  if p := s.providers[provider.id]; p != nil {
   return p, true
  }
 }

 return nil, false
}

func (c *Context) hasProvider(m *moduleInfo, provider *providerKey) bool {
 validateProvider(c, m, provider)
 maybeRestoreProviders(c, &m.commonIncrementalInfo, provider)
 if len(m.providers) > provider.id {
  if p := m.providers[provider.id]; p != nil {
   return true
  }
 }

 return false
}

func maybeRestoreProviders(c *Context, m *commonIncrementalInfo, provider *providerKey) {
 if provider.mutator != "" && provider.mutator != singletonTag {
  return
 }

 if m.incrementalRestored && m.hasUnrestoredProvider[provider.id] {
  func() {
   m.providerRestoreLock.Lock()
   defer m.providerRestoreLock.Unlock()
   if m.hasUnrestoredProvider[provider.id] {
    p, err := c.keyValueStoreCache.readProvider(c.EncContext, m.providerInitialValueHashes[provider.id], provider)
    if err != nil {
     panic(err)
    }
    if m.providers == nil {
     m.providers = make([]any, len(providerRegistry))
    }
    if m.providers[provider.id] != nil {
     panic(fmt.Sprintf("Value of provider %s is already set", provider.typ))
    }
    if p.Value != nil {
     m.providers[provider.id] = p.Value
    }
    m.hasUnrestoredProvider[provider.id] = false
   }
  }()
 }
}

func validateProvider(c *Context, m *moduleInfo, provider *providerKey) {
 if provider.mutator == "" {
  if !m.finishedGenerateBuildActions {
   panic(fmt.Sprintf("Can't get value of provider %s before GenerateBuildActions finished",
    provider.typ))
  }
 } else {
  expectedMutator := c.providerMutators[provider.id]
  if expectedMutator != nil && !c.mutatorFinishedForModule(expectedMutator, m) {
   panic(fmt.Sprintf("Can't get value of provider %s before mutator %s finished",
    provider.typ, provider.mutator))
  }
 }
}

func validateSingletonProvider(s *singletonInfo, provider *providerKey) {
 if provider.mutator != singletonTag {
  panic(fmt.Sprintf("Can't get value of non-singleton provider %s usign singleton specific get method", provider.typ))
 } else if !s.finishedGenerateBuildActions {
  panic(fmt.Sprintf("Can't get value of singleton provider %s before %s's GenerateBuildActions finished",
   provider.typ, s.name))
 }
}

func (c *Context) mutatorFinishedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
 if m.createdOnDemand {
  return m.finishedMutator >= mutator.index
 }
 if c.finishedMutators[mutator.index] {
  // mutator pass finished for all modules
  return true
 }

 return m.finishedMutator >= mutator.index
}

func (c *Context) mutatorStartedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
 if c.finishedMutators[mutator.index] {
  // mutator pass finished for all modules
  return true
 }

 return m.startedMutator >= mutator.index
}

// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
// for use in OtherModuleProvider.
type OtherModuleProviderContext interface {
 OtherModuleProvider(m ModuleOrProxy, provider AnyProviderKey) (any, bool)
}

var _ OtherModuleProviderContext = BaseModuleContext(nil)
var _ OtherModuleProviderContext = ModuleContext(nil)
var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)

// OtherModuleProvider reads the provider for the given module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set or the module is nil, the zero value
// of the provider's type  is returned and the boolean is false.  The value returned may be a deep
// copy of the value originally passed to SetProvider.
//
// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module ModuleOrProxy, provider ProviderKey[K]) (K, bool) {
 value, ok := ctx.OtherModuleProvider(module, provider)
 if !ok {
  var k K
  return k, false
 }
 return value.(K), ok
}

// SingletonModuleProviderContext is a helper interface that is a subset of Context and SingletonContext for use in
// SingletonModuleProvider.
type SingletonModuleProviderContext interface {
 ModuleProvider(m ModuleOrProxy, provider AnyProviderKey) (any, bool)
}

var _ SingletonModuleProviderContext = &Context{}
var _ SingletonModuleProviderContext = SingletonContext(nil)

// SingletonModuleProvider reads the provider for the given module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
//
// SingletonModuleProviderContext is a helper interface that accepts Context or SingletonContext.
func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module ModuleOrProxy, provider ProviderKey[K]) (K, bool) {
 value, ok := ctx.ModuleProvider(module, provider)
 if !ok {
  var k K
  return k, false
 }
 return value.(K), ok
}

// ModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
// for use in ModuleProvider.
type ModuleProviderContext interface {
 Provider(provider AnyProviderKey) (any, bool)
}

var _ ModuleProviderContext = BaseModuleContext(nil)
var _ ModuleProviderContext = ModuleContext(nil)
var _ ModuleProviderContext = BottomUpMutatorContext(nil)

// ModuleProvider reads the provider for the current module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
//
// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func ModuleProvider[K any](ctx ModuleProviderContext, provider ProviderKey[K]) (K, bool) {
 value, ok := ctx.Provider(provider)
 if !ok {
  var k K
  return k, false
 }
 return value.(K), ok
}

// SetProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
// for use in SetProvider.
type SetProviderContext interface {
 SetProvider(provider AnyProviderKey, value any)
}

var _ SetProviderContext = BaseModuleContext(nil)
var _ SetProviderContext = ModuleContext(nil)
var _ SetProviderContext = BottomUpMutatorContext(nil)

// SetProvider sets the value for a provider for the current module.  It panics if not called
// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
// is not of the appropriate type, or if the value has already been set.  The value should not
// be modified after being passed to SetProvider.
//
// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func SetProvider[K any](ctx SetProviderContext, provider ProviderKey[K], value K) {
 ctx.SetProvider(provider, value)
}

[Dauer der Verarbeitung: 0.22 Sekunden, vorverarbeitet 2026-06-28]