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 sharedLibraryProps struct {
106			Target struct {
107				Android *CodegenLibraryArchSharedProperties
108				Host    *CodegenLibraryArchSharedProperties
109			}
110		}
111
112		type staticLibraryProps struct {
113			Target struct {
114				Android *CodegenLibraryArchStaticProperties
115				Host    *CodegenLibraryArchStaticProperties
116			}
117		}
118
119		arch := getCodegenArchProperties(archName)
120
121		cp := &commonProps{}
122		sharedLP := &sharedLibraryProps{}
123		staticLP := &staticLibraryProps{}
124		if host {
125			cp.Target.Host = &arch.CodegenCommonArchProperties
126			sharedLP.Target.Host = &arch.CodegenLibraryArchSharedProperties
127			staticLP.Target.Host = &arch.CodegenLibraryArchStaticProperties
128		} else {
129			cp.Target.Android = &arch.CodegenCommonArchProperties
130			sharedLP.Target.Android = &arch.CodegenLibraryArchSharedProperties
131			staticLP.Target.Android = &arch.CodegenLibraryArchStaticProperties
132		}
133
134		ctx.AppendProperties(cp)
135		if t.library {
136			if t.static {
137				ctx.AppendProperties(staticLP)
138			}
139			if t.shared {
140				ctx.AppendProperties(sharedLP)
141			}
142		}
143	}
144
145	addCodegenProperties := func(host bool, arches []string) {
146		sourceProps := &CodegenSourceArchProperties{}
147		for _, arch := range arches {
148			appendCodegenSourceArchProperties(sourceProps, arch)
149			addCodegenArchProperties(host, arch)
150		}
151		sourceProps.Srcs = android.FirstUniqueStrings(sourceProps.Srcs)
152		addCodegenSourceArchProperties(host, sourceProps)
153	}
154
155	addCodegenProperties(false /* host */, deviceArches)
156	addCodegenProperties(true /* host */, hostArches)
157}
158
159// These properties are allowed to contain the same source file name in different architectures.
160// They we will be deduplicated automatically.
161type CodegenSourceArchProperties struct {
162	Srcs []string
163}
164
165type CodegenCommonArchProperties struct {
166	Cflags   []string
167	Cppflags []string
168}
169
170type CodegenLibraryArchStaticProperties struct {
171	Static struct {
172		Whole_static_libs []string
173	}
174}
175type CodegenLibraryArchSharedProperties struct {
176	Shared struct {
177		Shared_libs               []string
178		Export_shared_lib_headers []string
179	}
180}
181
182type codegenArchProperties struct {
183	CodegenSourceArchProperties
184	CodegenCommonArchProperties
185	CodegenLibraryArchStaticProperties
186	CodegenLibraryArchSharedProperties
187}
188
189type codegenProperties struct {
190	Codegen struct {
191		Arm, Arm64, X86, X86_64 codegenArchProperties
192	}
193}
194
195func defaultDeviceCodegenArches(ctx android.LoadHookContext) []string {
196	arches := make(map[string]bool)
197	for _, a := range ctx.DeviceConfig().Arches() {
198		s := a.ArchType.String()
199		arches[s] = true
200		if s == "arm64" {
201			arches["arm"] = true
202		} else if s == "x86_64" {
203			arches["x86"] = true
204		}
205	}
206	ret := make([]string, 0, len(arches))
207	for a := range arches {
208		ret = append(ret, a)
209	}
210	sort.Strings(ret)
211	return ret
212}
213
214func installCodegenCustomizer(module android.Module, t moduleType) {
215	c := &codegenProperties{}
216	android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, t) })
217	module.AddProperties(c)
218}
219