Golang程序  |  163行  |  4.09 KB

// Copyright (C) 2017 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 hal2vts

import (
	"path/filepath"
	"sort"
	"strings"
	"sync"

	"android/soong/android"
	"android/soong/genrule"

	"github.com/google/blueprint"
)

func init() {
	android.RegisterModuleType("hal2vts", hal2vtsFactory)
}

var (
	pctx = android.NewPackageContext("android/soong/hal2vts")

	hidlGen = pctx.HostBinToolVariable("hidlGen", "hidl-gen")

	hidlGenCmd = "${hidlGen} -o ${genDir} -L vts ${args} " +
		"${pckg}@${ver}::${halFile}"

	hal2vtsRule = pctx.StaticRule("hal2vtsRule", blueprint.RuleParams{
		Command:     hidlGenCmd,
		CommandDeps: []string{"${hidlGen}"},
		Description: "hidl-gen -l vts $in => $out",
	}, "genDir", "args", "pckg", "ver", "halFile")
)

type hal2vtsProperties struct {
	Hidl_gen_args string
	Srcs []string
	Out  []string
}

type hal2vts struct {
	android.ModuleBase

	properties hal2vtsProperties

	exportedHeaderDirs android.Paths
	generatedHeaders   android.Paths
}

var _ genrule.SourceFileGenerator = (*hal2vts)(nil)

func (h *hal2vts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	// Sort by name to match .hal to .vts file name.
	sort.Strings(h.properties.Out)
	srcFiles := ctx.ExpandSources(h.properties.Srcs, nil)
	sort.SliceStable(srcFiles, func(i, j int) bool {
		return strings.Compare(srcFiles[j].String(), srcFiles[i].String()) == 1
	})

	if len(srcFiles) != len(h.properties.Out) {
		ctx.ModuleErrorf("Number of inputs must be equal to number of outputs.")
	}

	args := h.properties.Hidl_gen_args

	genDir := android.PathForModuleGen(ctx, "").String()

	vtsList := vtsList(ctx.AConfig())

	vtsListMutex.Lock()
	defer vtsListMutex.Unlock()

	for i, src := range srcFiles {
		out := android.PathForModuleGen(ctx, h.properties.Out[i])
		if src.Ext() != ".hal" {
			ctx.ModuleErrorf("Source file has to be a .hal file.")
		}

		relOut, err := filepath.Rel(genDir, out.String())
		if err != nil {
			ctx.ModuleErrorf("Cannot get relative output path.")
		}
		halDir := filepath.Dir(relOut)
		halFile := strings.TrimSuffix(src.Base(), ".hal")

		ver := filepath.Base(halDir)
		// Need this to transform directory path to hal name.
		// For example, audio/effect -> audio.effect
		pckg := strings.Replace(filepath.Dir(halDir), "/", ".", -1)

		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
			Rule:   hal2vtsRule,
			Input:  src,
			Output: out,
			Args: map[string]string{
				"genDir":  genDir,
				"args":    args,
				"pckg":    pckg,
				"ver":     ver,
				"halFile": halFile,
			},
		})
		h.generatedHeaders = append(h.generatedHeaders, out)
		*vtsList = append(*vtsList, out)
	}
	h.exportedHeaderDirs = append(h.exportedHeaderDirs, android.PathForModuleGen(ctx, ""))
}

func (h *hal2vts) DepsMutator(ctx android.BottomUpMutatorContext) {
	android.ExtractSourcesDeps(ctx, h.properties.Srcs)
}

func (h *hal2vts) GeneratedHeaderDirs() android.Paths {
	return h.exportedHeaderDirs
}

func (h *hal2vts) GeneratedSourceFiles() android.Paths {
	return nil
}

func (h *hal2vts) GeneratedDeps() android.Paths {
	return h.generatedHeaders
}

func hal2vtsFactory() android.Module {
	h := &hal2vts{}
	h.AddProperties(&h.properties)
	android.InitAndroidModule(h)
	return h
}

func vtsList(config android.Config) *android.Paths {
	return config.Once("vtsList", func() interface{} {
		return &android.Paths{}
	}).(*android.Paths)
}

var vtsListMutex sync.Mutex

func init() {
	android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
}

func makeVarsProvider(ctx android.MakeVarsContext) {
	vtsList := vtsList(ctx.Config()).Strings()
	sort.Strings(vtsList)

	ctx.Strict("VTS_SPEC_FILE_LIST", strings.Join(vtsList, " "))
}