Home | History | Annotate | Download | only in android
      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 	"fmt"
     19 
     20 	"github.com/google/blueprint"
     21 	"github.com/google/blueprint/proptools"
     22 )
     23 
     24 // This file implements common functionality for handling modules that may exist as prebuilts,
     25 // source, or both.
     26 
     27 type prebuiltDependencyTag struct {
     28 	blueprint.BaseDependencyTag
     29 }
     30 
     31 var prebuiltDepTag prebuiltDependencyTag
     32 
     33 type PrebuiltProperties struct {
     34 	// When prefer is set to true the prebuilt will be used instead of any source module with
     35 	// a matching name.
     36 	Prefer *bool `android:"arch_variant"`
     37 
     38 	SourceExists bool `blueprint:"mutated"`
     39 	UsePrebuilt  bool `blueprint:"mutated"`
     40 }
     41 
     42 type Prebuilt struct {
     43 	properties PrebuiltProperties
     44 	module     Module
     45 	srcs       *[]string
     46 	src        *string
     47 }
     48 
     49 func (p *Prebuilt) Name(name string) string {
     50 	return "prebuilt_" + name
     51 }
     52 
     53 func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
     54 	if p.srcs != nil {
     55 		if len(*p.srcs) == 0 {
     56 			ctx.PropertyErrorf("srcs", "missing prebuilt source file")
     57 			return nil
     58 		}
     59 
     60 		if len(*p.srcs) > 1 {
     61 			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
     62 			return nil
     63 		}
     64 
     65 		// Return the singleton source after expanding any filegroup in the
     66 		// sources.
     67 		return PathForModuleSrc(ctx, (*p.srcs)[0])
     68 	} else {
     69 		if proptools.String(p.src) == "" {
     70 			ctx.PropertyErrorf("src", "missing prebuilt source file")
     71 			return nil
     72 		}
     73 		return PathForModuleSrc(ctx, *p.src)
     74 	}
     75 }
     76 
     77 func (p *Prebuilt) UsePrebuilt() bool {
     78 	return p.properties.UsePrebuilt
     79 }
     80 
     81 func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
     82 	p := module.Prebuilt()
     83 	module.AddProperties(&p.properties)
     84 	p.srcs = srcs
     85 }
     86 
     87 func InitSingleSourcePrebuiltModule(module PrebuiltInterface, src *string) {
     88 	p := module.Prebuilt()
     89 	module.AddProperties(&p.properties)
     90 	p.src = src
     91 }
     92 
     93 type PrebuiltInterface interface {
     94 	Module
     95 	Prebuilt() *Prebuilt
     96 }
     97 
     98 func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
     99 	ctx.BottomUp("prebuilts", PrebuiltMutator).Parallel()
    100 }
    101 
    102 func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
    103 	ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
    104 	ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
    105 }
    106 
    107 // PrebuiltMutator ensures that there is always a module with an undecorated name, and marks
    108 // prebuilt modules that have both a prebuilt and a source module.
    109 func PrebuiltMutator(ctx BottomUpMutatorContext) {
    110 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
    111 		p := m.Prebuilt()
    112 		name := m.base().BaseModuleName()
    113 		if ctx.OtherModuleExists(name) {
    114 			ctx.AddReverseDependency(ctx.Module(), prebuiltDepTag, name)
    115 			p.properties.SourceExists = true
    116 		} else {
    117 			ctx.Rename(name)
    118 		}
    119 	}
    120 }
    121 
    122 // PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or
    123 // because the source module doesn't exist.  It also disables installing overridden source modules.
    124 func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
    125 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
    126 		p := m.Prebuilt()
    127 		if p.srcs == nil && p.src == nil {
    128 			panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
    129 		}
    130 		if !p.properties.SourceExists {
    131 			p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil)
    132 		}
    133 	} else if s, ok := ctx.Module().(Module); ok {
    134 		ctx.VisitDirectDepsWithTag(prebuiltDepTag, func(m Module) {
    135 			p := m.(PrebuiltInterface).Prebuilt()
    136 			if p.usePrebuilt(ctx, s) {
    137 				p.properties.UsePrebuilt = true
    138 				s.SkipInstall()
    139 			}
    140 		})
    141 	}
    142 }
    143 
    144 // PrebuiltPostDepsMutator does two operations.  It replace dependencies on the
    145 // source module with dependencies on the prebuilt when both modules exist and
    146 // the prebuilt should be used.  When the prebuilt should not be used, disable
    147 // installing it.  Secondly, it also adds a sourcegroup to any filegroups found
    148 // in the prebuilt's 'Srcs' property.
    149 func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
    150 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
    151 		p := m.Prebuilt()
    152 		name := m.base().BaseModuleName()
    153 		if p.properties.UsePrebuilt {
    154 			if p.properties.SourceExists {
    155 				ctx.ReplaceDependencies(name)
    156 			}
    157 		} else {
    158 			m.SkipInstall()
    159 		}
    160 	}
    161 }
    162 
    163 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
    164 // will be used if it is marked "prefer" or if the source module is disabled.
    165 func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
    166 	if p.srcs != nil && len(*p.srcs) == 0 {
    167 		return false
    168 	}
    169 
    170 	if p.src != nil && *p.src == "" {
    171 		return false
    172 	}
    173 
    174 	// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
    175 	if Bool(p.properties.Prefer) {
    176 		return true
    177 	}
    178 
    179 	return source == nil || !source.Enabled()
    180 }
    181 
    182 func (p *Prebuilt) SourceExists() bool {
    183 	return p.properties.SourceExists
    184 }
    185