1// Copyright 2020 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
15package android
16
17import (
18	"fmt"
19	"io"
20	"path/filepath"
21
22	"github.com/google/blueprint/proptools"
23)
24
25func init() {
26	RegisterModuleType("makefile_goal", MakefileGoalFactory)
27}
28
29type makefileGoalProperties struct {
30	// Sources.
31
32	// Makefile goal output file path, relative to PRODUCT_OUT.
33	Product_out_path *string
34}
35
36type makefileGoal struct {
37	ModuleBase
38
39	properties makefileGoalProperties
40
41	// Destination. Output file path of this module.
42	outputFilePath OutputPath
43}
44
45var _ AndroidMkEntriesProvider = (*makefileGoal)(nil)
46var _ OutputFileProducer = (*makefileGoal)(nil)
47
48// Input file of this makefile_goal module. Nil if none specified. May use variable names in makefiles.
49func (p *makefileGoal) inputPath() *string {
50	if p.properties.Product_out_path != nil {
51		return proptools.StringPtr(filepath.Join("$(PRODUCT_OUT)", proptools.String(p.properties.Product_out_path)))
52	}
53	return nil
54}
55
56// OutputFileProducer
57func (p *makefileGoal) OutputFiles(tag string) (Paths, error) {
58	if tag != "" {
59		return nil, fmt.Errorf("unsupported tag %q", tag)
60	}
61	return Paths{p.outputFilePath}, nil
62}
63
64// AndroidMkEntriesProvider
65func (p *makefileGoal) DepsMutator(ctx BottomUpMutatorContext) {
66	if p.inputPath() == nil {
67		ctx.PropertyErrorf("product_out_path", "Path relative to PRODUCT_OUT required")
68	}
69}
70
71func (p *makefileGoal) GenerateAndroidBuildActions(ctx ModuleContext) {
72	filename := filepath.Base(proptools.String(p.inputPath()))
73	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
74
75	ctx.InstallFile(PathForModuleInstall(ctx, "etc"), ctx.ModuleName(), p.outputFilePath)
76}
77
78func (p *makefileGoal) AndroidMkEntries() []AndroidMkEntries {
79	return []AndroidMkEntries{AndroidMkEntries{
80		Class:      "ETC",
81		OutputFile: OptionalPathForPath(p.outputFilePath),
82		ExtraFooters: []AndroidMkExtraFootersFunc{
83			func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries) {
84				// Can't use Cp because inputPath() is not a valid Path.
85				fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,%s))\n", proptools.String(p.inputPath()), p.outputFilePath)
86			},
87		},
88	}}
89}
90
91// Import a Makefile goal to Soong by copying the file built by
92// the goal to a path visible to Soong. This rule only works on boot images.
93func MakefileGoalFactory() Module {
94	module := &makefileGoal{}
95	module.AddProperties(&module.properties)
96	// This module is device-only
97	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
98	return module
99}
100