blob: f041b597ffe5ad0540487d230473d2da543742bb [file] [log] [blame]
Dan Willemsen218f6562015-07-08 18:13:11 -07001// Copyright 2015 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 common
16
17import (
18 "bytes"
Dan Willemsen97750522016-02-09 17:43:51 -080019 "fmt"
Dan Willemsen218f6562015-07-08 18:13:11 -070020 "io"
21 "io/ioutil"
22 "os"
23 "path/filepath"
24 "sort"
25
26 "android/soong"
27
28 "github.com/google/blueprint"
29)
30
31func init() {
32 soong.RegisterSingletonType("androidmk", AndroidMkSingleton)
33}
34
35type AndroidMkDataProvider interface {
Dan Willemsen97750522016-02-09 17:43:51 -080036 AndroidMk() (AndroidMkData, error)
Dan Willemsen218f6562015-07-08 18:13:11 -070037}
38
39type AndroidMkData struct {
40 Class string
Dan Willemsen34cc69e2015-09-23 15:26:20 -070041 OutputFile OptionalPath
Dan Willemsen218f6562015-07-08 18:13:11 -070042
Dan Willemsen97750522016-02-09 17:43:51 -080043 Custom func(w io.Writer, name, prefix string) error
Dan Willemsen218f6562015-07-08 18:13:11 -070044
Dan Willemsen97750522016-02-09 17:43:51 -080045 Extra func(w io.Writer, outputFile Path) error
Dan Willemsen218f6562015-07-08 18:13:11 -070046}
47
48func AndroidMkSingleton() blueprint.Singleton {
49 return &androidMkSingleton{}
50}
51
52type androidMkSingleton struct{}
53
54func (c *androidMkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
Dan Willemsen5ba07e82015-12-11 13:51:06 -080055 if !ctx.Config().(Config).EmbeddedInMake() {
56 return
57 }
58
Dan Willemsen34cc69e2015-09-23 15:26:20 -070059 ctx.SetNinjaBuildDir(pctx, filepath.Join(ctx.Config().(Config).buildDir, ".."))
Dan Willemsen218f6562015-07-08 18:13:11 -070060
Colin Cross4f6e4e62016-01-11 12:55:55 -080061 var androidMkModulesList []AndroidModule
62
Dan Willemsen218f6562015-07-08 18:13:11 -070063 ctx.VisitAllModules(func(module blueprint.Module) {
Colin Cross4f6e4e62016-01-11 12:55:55 -080064 if amod, ok := module.(AndroidModule); ok {
Dan Willemsen218f6562015-07-08 18:13:11 -070065 androidMkModulesList = append(androidMkModulesList, amod)
66 }
Colin Cross4f6e4e62016-01-11 12:55:55 -080067 })
Dan Willemsen218f6562015-07-08 18:13:11 -070068
Colin Crossd779da42015-12-17 18:00:23 -080069 sort.Sort(AndroidModulesByName{androidMkModulesList, ctx})
70
Dan Willemsen34cc69e2015-09-23 15:26:20 -070071 transMk := PathForOutput(ctx, "Android.mk")
72 if ctx.Failed() {
73 return
74 }
Dan Willemsen218f6562015-07-08 18:13:11 -070075
Dan Willemsen34cc69e2015-09-23 15:26:20 -070076 err := translateAndroidMk(ctx, transMk.String(), androidMkModulesList)
Dan Willemsen218f6562015-07-08 18:13:11 -070077 if err != nil {
78 ctx.Errorf(err.Error())
79 }
80
81 ctx.Build(pctx, blueprint.BuildParams{
82 Rule: blueprint.Phony,
Dan Willemsen34cc69e2015-09-23 15:26:20 -070083 Outputs: []string{transMk.String()},
Dan Willemsen218f6562015-07-08 18:13:11 -070084 Optional: true,
85 })
86}
87
88func translateAndroidMk(ctx blueprint.SingletonContext, mkFile string, mods []AndroidModule) error {
89 buf := &bytes.Buffer{}
90
Dan Willemsen97750522016-02-09 17:43:51 -080091 fmt.Fprintln(buf, "LOCAL_PATH := $(TOP)")
92 fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
Dan Willemsen218f6562015-07-08 18:13:11 -070093
94 for _, mod := range mods {
95 err := translateAndroidMkModule(ctx, buf, mod)
96 if err != nil {
97 os.Remove(mkFile)
98 return err
99 }
100 }
101
102 // Don't write to the file if it hasn't changed
103 if _, err := os.Stat(mkFile); !os.IsNotExist(err) {
104 if data, err := ioutil.ReadFile(mkFile); err == nil {
105 matches := buf.Len() == len(data)
106
107 if matches {
108 for i, value := range buf.Bytes() {
109 if value != data[i] {
110 matches = false
111 break
112 }
113 }
114 }
115
116 if matches {
117 return nil
118 }
119 }
120 }
121
122 return ioutil.WriteFile(mkFile, buf.Bytes(), 0666)
123}
124
125func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod blueprint.Module) error {
Dan Willemsen97750522016-02-09 17:43:51 -0800126 name := ctx.ModuleName(mod)
127
128 provider, ok := mod.(AndroidMkDataProvider)
129 if !ok {
Dan Willemsen218f6562015-07-08 18:13:11 -0700130 return nil
131 }
132
Dan Willemsen97750522016-02-09 17:43:51 -0800133 amod := mod.(AndroidModule).base()
134 data, err := provider.AndroidMk()
135 if err != nil {
136 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700137 }
138
Dan Willemsen97750522016-02-09 17:43:51 -0800139 if !amod.Enabled() {
140 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700141 }
142
Dan Willemsen97750522016-02-09 17:43:51 -0800143 hostCross := false
144 if amod.Host() && amod.HostType() != CurrentHostType() {
145 hostCross = true
146 }
Dan Willemsen218f6562015-07-08 18:13:11 -0700147
Dan Willemsen97750522016-02-09 17:43:51 -0800148 if data.Custom != nil {
Dan Willemsen218f6562015-07-08 18:13:11 -0700149 prefix := ""
Dan Willemsen97750522016-02-09 17:43:51 -0800150 if amod.Host() {
151 if hostCross {
152 prefix = "HOST_CROSS_"
153 } else {
154 prefix = "HOST_"
155 }
156 if amod.Arch().ArchType != ctx.Config().(Config).HostArches[amod.HostType()][0].ArchType {
157 prefix = "2ND_" + prefix
Dan Willemsen218f6562015-07-08 18:13:11 -0700158 }
159 } else {
Dan Willemsen97750522016-02-09 17:43:51 -0800160 prefix = "TARGET_"
161 if amod.Arch().ArchType != ctx.Config().(Config).DeviceArches[0].ArchType {
162 prefix = "2ND_" + prefix
Dan Willemsen218f6562015-07-08 18:13:11 -0700163 }
164 }
165
Dan Willemsen97750522016-02-09 17:43:51 -0800166 return data.Custom(w, name, prefix)
Dan Willemsen218f6562015-07-08 18:13:11 -0700167 }
168
Dan Willemsen97750522016-02-09 17:43:51 -0800169 if !data.OutputFile.Valid() {
170 return err
171 }
172
173 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
174 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
175 fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", data.Class)
176 fmt.Fprintln(w, "LOCAL_MULTILIB :=", amod.commonProperties.Compile_multilib)
177 fmt.Fprintln(w, "LOCAL_SRC_FILES :=", data.OutputFile.String())
178
179 archStr := amod.Arch().ArchType.String()
180 if amod.Host() {
181 if hostCross {
182 fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
183 } else {
184 fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
185
186 // TODO: this isn't true for every module, only dependencies of ACP
187 fmt.Fprintln(w, "LOCAL_ACP_UNAVAILABLE := true")
188 }
189 fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", amod.HostType().String())
190 fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
191 } else {
192 fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
193 }
194
195 if data.Extra != nil {
196 err = data.Extra(w, data.OutputFile.Path())
197 if err != nil {
198 return err
199 }
200 }
201
202 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
203
204 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700205}