github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/android/hooks.go (about)

     1  // Copyright 2016 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package android
    16  
    17  import (
    18  	"github.com/google/blueprint"
    19  )
    20  
    21  // This file implements hooks that external module types can use to inject logic into existing
    22  // module types.  Each hook takes an interface as a parameter so that new methods can be added
    23  // to the interface without breaking existing module types.
    24  
    25  // Load hooks are run after the module's properties have been filled from the blueprint file, but
    26  // before the module has been split into architecture variants, and before defaults modules have
    27  // been applied.
    28  type LoadHookContext interface {
    29  	// TODO: a new context that includes Config() but not Target(), etc.?
    30  	BaseContext
    31  	AppendProperties(...interface{})
    32  	PrependProperties(...interface{})
    33  	CreateModule(blueprint.ModuleFactory, ...interface{})
    34  }
    35  
    36  // Arch hooks are run after the module has been split into architecture variants, and can be used
    37  // to add architecture-specific properties.
    38  type ArchHookContext interface {
    39  	BaseContext
    40  	AppendProperties(...interface{})
    41  	PrependProperties(...interface{})
    42  }
    43  
    44  func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) {
    45  	h := &m.(Module).base().hooks
    46  	h.load = append(h.load, hook)
    47  }
    48  
    49  func AddArchHook(m blueprint.Module, hook func(ArchHookContext)) {
    50  	h := &m.(Module).base().hooks
    51  	h.arch = append(h.arch, hook)
    52  }
    53  
    54  func (x *hooks) runLoadHooks(ctx LoadHookContext, m *ModuleBase) {
    55  	if len(x.load) > 0 {
    56  		for _, x := range x.load {
    57  			x(ctx)
    58  			if ctx.Failed() {
    59  				return
    60  			}
    61  		}
    62  	}
    63  }
    64  
    65  func (x *hooks) runArchHooks(ctx ArchHookContext, m *ModuleBase) {
    66  	if len(x.arch) > 0 {
    67  		for _, x := range x.arch {
    68  			x(ctx)
    69  			if ctx.Failed() {
    70  				return
    71  			}
    72  		}
    73  	}
    74  }
    75  
    76  type InstallHookContext interface {
    77  	ModuleContext
    78  	Path() OutputPath
    79  	Symlink() bool
    80  }
    81  
    82  // Install hooks are run after a module creates a rule to install a file or symlink.
    83  // The installed path is available from InstallHookContext.Path(), and
    84  // InstallHookContext.Symlink() will be true if it was a symlink.
    85  func AddInstallHook(m blueprint.Module, hook func(InstallHookContext)) {
    86  	h := &m.(Module).base().hooks
    87  	h.install = append(h.install, hook)
    88  }
    89  
    90  type installHookContext struct {
    91  	ModuleContext
    92  	path    OutputPath
    93  	symlink bool
    94  }
    95  
    96  func (x *installHookContext) Path() OutputPath {
    97  	return x.path
    98  }
    99  
   100  func (x *installHookContext) Symlink() bool {
   101  	return x.symlink
   102  }
   103  
   104  func (x *hooks) runInstallHooks(ctx ModuleContext, path OutputPath, symlink bool) {
   105  	if len(x.install) > 0 {
   106  		mctx := &installHookContext{
   107  			ModuleContext: ctx,
   108  			path:          path,
   109  			symlink:       symlink,
   110  		}
   111  		for _, x := range x.install {
   112  			x(mctx)
   113  			if mctx.Failed() {
   114  				return
   115  			}
   116  		}
   117  	}
   118  }
   119  
   120  type hooks struct {
   121  	load    []func(LoadHookContext)
   122  	arch    []func(ArchHookContext)
   123  	install []func(InstallHookContext)
   124  }
   125  
   126  func loadHookMutator(ctx TopDownMutatorContext) {
   127  	if m, ok := ctx.Module().(Module); ok {
   128  		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
   129  		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
   130  		var loadHookCtx LoadHookContext = ctx.(*androidTopDownMutatorContext)
   131  		m.base().hooks.runLoadHooks(loadHookCtx, m.base())
   132  	}
   133  }
   134  
   135  func archHookMutator(ctx TopDownMutatorContext) {
   136  	if m, ok := ctx.Module().(Module); ok {
   137  		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
   138  		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
   139  		var archHookCtx ArchHookContext = ctx.(*androidTopDownMutatorContext)
   140  		m.base().hooks.runArchHooks(archHookCtx, m.base())
   141  	}
   142  }