blob: a16a652d8cff6a07b60b86a7ae13234ff692716d [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
Colin Crossa2344662016-03-24 13:14:12 -070041 SubName string
Dan Willemsen34cc69e2015-09-23 15:26:20 -070042 OutputFile OptionalPath
Colin Crossca860ac2016-01-04 14:34:37 -080043 Disabled bool
Dan Willemsen218f6562015-07-08 18:13:11 -070044
Dan Willemsen97750522016-02-09 17:43:51 -080045 Custom func(w io.Writer, name, prefix string) error
Dan Willemsen218f6562015-07-08 18:13:11 -070046
Colin Crossca860ac2016-01-04 14:34:37 -080047 Extra []func(w io.Writer, outputFile Path) error
Dan Willemsen218f6562015-07-08 18:13:11 -070048}
49
50func AndroidMkSingleton() blueprint.Singleton {
51 return &androidMkSingleton{}
52}
53
54type androidMkSingleton struct{}
55
56func (c *androidMkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
Dan Willemsen5ba07e82015-12-11 13:51:06 -080057 if !ctx.Config().(Config).EmbeddedInMake() {
58 return
59 }
60
Dan Willemsen34cc69e2015-09-23 15:26:20 -070061 ctx.SetNinjaBuildDir(pctx, filepath.Join(ctx.Config().(Config).buildDir, ".."))
Dan Willemsen218f6562015-07-08 18:13:11 -070062
Colin Cross4f6e4e62016-01-11 12:55:55 -080063 var androidMkModulesList []AndroidModule
64
Dan Willemsen218f6562015-07-08 18:13:11 -070065 ctx.VisitAllModules(func(module blueprint.Module) {
Colin Cross4f6e4e62016-01-11 12:55:55 -080066 if amod, ok := module.(AndroidModule); ok {
Dan Willemsen218f6562015-07-08 18:13:11 -070067 androidMkModulesList = append(androidMkModulesList, amod)
68 }
Colin Cross4f6e4e62016-01-11 12:55:55 -080069 })
Dan Willemsen218f6562015-07-08 18:13:11 -070070
Colin Crossd779da42015-12-17 18:00:23 -080071 sort.Sort(AndroidModulesByName{androidMkModulesList, ctx})
72
Dan Willemsen34cc69e2015-09-23 15:26:20 -070073 transMk := PathForOutput(ctx, "Android.mk")
74 if ctx.Failed() {
75 return
76 }
Dan Willemsen218f6562015-07-08 18:13:11 -070077
Dan Willemsen34cc69e2015-09-23 15:26:20 -070078 err := translateAndroidMk(ctx, transMk.String(), androidMkModulesList)
Dan Willemsen218f6562015-07-08 18:13:11 -070079 if err != nil {
80 ctx.Errorf(err.Error())
81 }
82
83 ctx.Build(pctx, blueprint.BuildParams{
84 Rule: blueprint.Phony,
Dan Willemsen34cc69e2015-09-23 15:26:20 -070085 Outputs: []string{transMk.String()},
Dan Willemsen218f6562015-07-08 18:13:11 -070086 Optional: true,
87 })
88}
89
90func translateAndroidMk(ctx blueprint.SingletonContext, mkFile string, mods []AndroidModule) error {
91 buf := &bytes.Buffer{}
92
Dan Willemsen97750522016-02-09 17:43:51 -080093 fmt.Fprintln(buf, "LOCAL_PATH := $(TOP)")
94 fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
Dan Willemsen218f6562015-07-08 18:13:11 -070095
96 for _, mod := range mods {
97 err := translateAndroidMkModule(ctx, buf, mod)
98 if err != nil {
99 os.Remove(mkFile)
100 return err
101 }
102 }
103
104 // Don't write to the file if it hasn't changed
105 if _, err := os.Stat(mkFile); !os.IsNotExist(err) {
106 if data, err := ioutil.ReadFile(mkFile); err == nil {
107 matches := buf.Len() == len(data)
108
109 if matches {
110 for i, value := range buf.Bytes() {
111 if value != data[i] {
112 matches = false
113 break
114 }
115 }
116 }
117
118 if matches {
119 return nil
120 }
121 }
122 }
123
124 return ioutil.WriteFile(mkFile, buf.Bytes(), 0666)
125}
126
127func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod blueprint.Module) error {
Dan Willemsen97750522016-02-09 17:43:51 -0800128 name := ctx.ModuleName(mod)
129
130 provider, ok := mod.(AndroidMkDataProvider)
131 if !ok {
Dan Willemsen218f6562015-07-08 18:13:11 -0700132 return nil
133 }
134
Dan Willemsen97750522016-02-09 17:43:51 -0800135 amod := mod.(AndroidModule).base()
136 data, err := provider.AndroidMk()
137 if err != nil {
138 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700139 }
140
Dan Willemsen97750522016-02-09 17:43:51 -0800141 if !amod.Enabled() {
142 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700143 }
144
Colin Crossa2344662016-03-24 13:14:12 -0700145 if data.SubName != "" {
146 name += "_" + data.SubName
147 }
148
Dan Willemsen97750522016-02-09 17:43:51 -0800149 hostCross := false
150 if amod.Host() && amod.HostType() != CurrentHostType() {
151 hostCross = true
152 }
Dan Willemsen218f6562015-07-08 18:13:11 -0700153
Dan Willemsen97750522016-02-09 17:43:51 -0800154 if data.Custom != nil {
Dan Willemsen218f6562015-07-08 18:13:11 -0700155 prefix := ""
Dan Willemsen97750522016-02-09 17:43:51 -0800156 if amod.Host() {
157 if hostCross {
158 prefix = "HOST_CROSS_"
159 } else {
160 prefix = "HOST_"
161 }
162 if amod.Arch().ArchType != ctx.Config().(Config).HostArches[amod.HostType()][0].ArchType {
163 prefix = "2ND_" + prefix
Dan Willemsen218f6562015-07-08 18:13:11 -0700164 }
165 } else {
Dan Willemsen97750522016-02-09 17:43:51 -0800166 prefix = "TARGET_"
167 if amod.Arch().ArchType != ctx.Config().(Config).DeviceArches[0].ArchType {
168 prefix = "2ND_" + prefix
Dan Willemsen218f6562015-07-08 18:13:11 -0700169 }
170 }
171
Dan Willemsen97750522016-02-09 17:43:51 -0800172 return data.Custom(w, name, prefix)
Dan Willemsen218f6562015-07-08 18:13:11 -0700173 }
174
Colin Crossca860ac2016-01-04 14:34:37 -0800175 if data.Disabled {
176 return nil
177 }
178
Dan Willemsen97750522016-02-09 17:43:51 -0800179 if !data.OutputFile.Valid() {
180 return err
181 }
182
183 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
184 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
185 fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", data.Class)
186 fmt.Fprintln(w, "LOCAL_MULTILIB :=", amod.commonProperties.Compile_multilib)
187 fmt.Fprintln(w, "LOCAL_SRC_FILES :=", data.OutputFile.String())
188
189 archStr := amod.Arch().ArchType.String()
190 if amod.Host() {
191 if hostCross {
192 fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
193 } else {
194 fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
Dan Willemsen97750522016-02-09 17:43:51 -0800195 }
196 fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", amod.HostType().String())
197 fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
198 } else {
199 fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
200 }
201
Colin Crossca860ac2016-01-04 14:34:37 -0800202 for _, extra := range data.Extra {
203 err = extra(w, data.OutputFile.Path())
Dan Willemsen97750522016-02-09 17:43:51 -0800204 if err != nil {
205 return err
206 }
207 }
208
209 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
210
211 return err
Dan Willemsen218f6562015-07-08 18:13:11 -0700212}