1// Copyright (C) 2016 The Android Open Source Project
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 art
16
17// This file implements the "codegen" property to apply different properties based on the currently
18// selected codegen arches, which defaults to all arches on the host and the primary and secondary
19// arches on the device.
20
21import (
22	"sort"
23	"strings"
24
25	"android/soong/android"
26)
27
28type moduleType struct {
29	library bool
30	static  bool
31	shared  bool
32}
33
34var (
35	staticLibrary          = moduleType{true, true, false}
36	sharedLibrary          = moduleType{true, false, true}
37	staticAndSharedLibrary = moduleType{true, true, true}
38	binary                 = moduleType{false, false, false}
39)
40
41func codegen(ctx android.LoadHookContext, c *codegenProperties, t moduleType) {
42	var hostArches, deviceArches []string
43
44	e := ctx.Config().Getenv("ART_HOST_CODEGEN_ARCHS")
45	if e == "" {
46		hostArches = supportedArches
47	} else {
48		hostArches = strings.Split(e, " ")
49	}
50
51	e = ctx.Config().Getenv("ART_TARGET_CODEGEN_ARCHS")
52	if e == "" {
53		deviceArches = defaultDeviceCodegenArches(ctx)
54	} else {
55		deviceArches = strings.Split(e, " ")
56	}
57
58	getCodegenArchProperties := func(archName string) *codegenArchProperties {
59		var arch *codegenArchProperties
60		switch archName {
61		case "arm":
62			arch = &c.Codegen.Arm
63		case "arm64":
64			arch = &c.Codegen.Arm64
65		case "x86":
66			arch = &c.Codegen.X86
67		case "x86_64":
68			arch = &c.Codegen.X86_64
69		default:
70			ctx.ModuleErrorf("Unknown codegen architecture %q", archName)
71		}
72		return arch
73	}
74
75	appendCodegenSourceArchProperties := func(p *CodegenSourceArchProperties, archName string) {
76		arch := getCodegenArchProperties(archName)
77		p.Srcs = append(p.Srcs, arch.CodegenSourceArchProperties.Srcs...)
78	}
79
80	addCodegenSourceArchProperties := func(host bool, p *CodegenSourceArchProperties) {
81		type sourceProps struct {
82			Target struct {
83				Android *CodegenSourceArchProperties
84				Host    *CodegenSourceArchProperties
85			}
86		}
87
88		sp := &sourceProps{}
89		if host {
90			sp.Target.Host = p
91		} else {
92			sp.Target.Android = p
93		}
94		ctx.AppendProperties(sp)
95	}
96
97	addCodegenArchProperties := func(host bool, archName string) {
98		type commonProps struct {
99			Target struct {
100				Android *CodegenCommonArchProperties
101				Host    *CodegenCommonArchProperties
102			}
103		}
104
105		type libraryProps struct {
106			Target struct {
107				Android *CodegenLibraryArchProperties
108				Host    *CodegenLibraryArchProperties
109			}
110		}
111
112		type sharedLibraryProps struct {
113			Target struct {
114				Android *CodegenLibraryArchSharedProperties
115				Host    *CodegenLibraryArchSharedProperties
116			}
117		}
118
119		type staticLibraryProps struct {
120			Target struct {
121				Android *CodegenLibraryArchStaticProperties
122				Host    *CodegenLibraryArchStaticProperties
123			}
124		}
125
126		arch := getCodegenArchProperties(archName)
127
128		cp := &commonProps{}
129		lp := &libraryProps{}
130		sharedLP := &sharedLibraryProps{}
131		staticLP := &staticLibraryProps{}
132		if host {
133			cp.Target.Host = &arch.CodegenCommonArchProperties
134			lp.Target.Host = &arch.CodegenLibraryArchProperties
135			sharedLP.Target.Host = &arch.CodegenLibraryArchSharedProperties
136			staticLP.Target.Host = &arch.CodegenLibraryArchStaticProperties
137		} else {
138			cp.Target.Android = &arch.CodegenCommonArchProperties
139			lp.Target.Android = &arch.CodegenLibraryArchProperties
140			sharedLP.Target.Android = &arch.CodegenLibraryArchSharedProperties
141			staticLP.Target.Android = &arch.CodegenLibraryArchStaticProperties
142		}
143
144		ctx.AppendProperties(cp)
145		if t.library {
146			ctx.AppendProperties(lp)
147			if t.static {
148				ctx.AppendProperties(staticLP)
149			}
150			if t.shared {
151				ctx.AppendProperties(sharedLP)
152			}
153		}
154	}
155
156	addCodegenProperties := func(host bool, arches []string) {
157		sourceProps := &CodegenSourceArchProperties{}
158		for _, arch := range arches {
159			appendCodegenSourceArchProperties(sourceProps, arch)
160			addCodegenArchProperties(host, arch)
161		}
162		sourceProps.Srcs = android.FirstUniqueStrings(sourceProps.Srcs)
163		addCodegenSourceArchProperties(host, sourceProps)
164	}
165
166	addCodegenProperties(false /* host */, deviceArches)
167	addCodegenProperties(true /* host */, hostArches)
168}
169
170// These properties are allowed to contain the same source file name in different architectures.
171// They we will be deduplicated automatically.
172type CodegenSourceArchProperties struct {
173	Srcs []string
174}
175
176type CodegenCommonArchProperties struct {
177	Cflags   []string
178	Cppflags []string
179}
180
181type CodegenLibraryArchProperties struct {
182	Static_libs               []string
183	Export_static_lib_headers []string
184}
185
186type CodegenLibraryArchStaticProperties struct {
187	Static struct {
188		Whole_static_libs []string
189	}
190}
191type CodegenLibraryArchSharedProperties struct {
192	Shared struct {
193		Shared_libs               []string
194		Export_shared_lib_headers []string
195	}
196}
197
198type codegenArchProperties struct {
199	CodegenSourceArchProperties
200	CodegenCommonArchProperties
201	CodegenLibraryArchProperties
202	CodegenLibraryArchStaticProperties
203	CodegenLibraryArchSharedProperties
204}
205
206type codegenProperties struct {
207	Codegen struct {
208		Arm, Arm64, X86, X86_64 codegenArchProperties
209	}
210}
211
212func defaultDeviceCodegenArches(ctx android.LoadHookContext) []string {
213	arches := make(map[string]bool)
214	for _, a := range ctx.DeviceConfig().Arches() {
215		s := a.ArchType.String()
216		arches[s] = true
217		if s == "arm64" {
218			arches["arm"] = true
219		} else if s == "x86_64" {
220			arches["x86"] = true
221		}
222	}
223	ret := make([]string, 0, len(arches))
224	for a := range arches {
225		ret = append(ret, a)
226	}
227	sort.Strings(ret)
228	return ret
229}
230
231func installCodegenCustomizer(module android.Module, t moduleType) {
232	c := &codegenProperties{}
233	android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, t) })
234	module.AddProperties(c)
235}
236