• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package main
2
3import (
4	mkparser "android/soong/androidmk/parser"
5	"fmt"
6	"strings"
7
8	bpparser "github.com/google/blueprint/parser"
9)
10
11const (
12	clear_vars = "__android_mk_clear_vars"
13)
14
15var standardProperties = map[string]struct {
16	string
17	bpparser.ValueType
18}{
19	// String properties
20	"LOCAL_MODULE":               {"name", bpparser.String},
21	"LOCAL_MODULE_CLASS":         {"class", bpparser.String},
22	"LOCAL_CXX_STL":              {"stl", bpparser.String},
23	"LOCAL_STRIP_MODULE":         {"strip", bpparser.String},
24	"LOCAL_MULTILIB":             {"compile_multilib", bpparser.String},
25	"LOCAL_ARM_MODE_HACK":        {"instruction_set", bpparser.String},
26	"LOCAL_SDK_VERSION":          {"sdk_version", bpparser.String},
27	"LOCAL_NDK_STL_VARIANT":      {"stl", bpparser.String},
28	"LOCAL_JAR_MANIFEST":         {"manifest", bpparser.String},
29	"LOCAL_JARJAR_RULES":         {"jarjar_rules", bpparser.String},
30	"LOCAL_CERTIFICATE":          {"certificate", bpparser.String},
31	"LOCAL_PACKAGE_NAME":         {"name", bpparser.String},
32	"LOCAL_MODULE_RELATIVE_PATH": {"relative_install_path", bpparser.String},
33
34	// List properties
35	"LOCAL_SRC_FILES":               {"srcs", bpparser.List},
36	"LOCAL_SHARED_LIBRARIES":        {"shared_libs", bpparser.List},
37	"LOCAL_STATIC_LIBRARIES":        {"static_libs", bpparser.List},
38	"LOCAL_WHOLE_STATIC_LIBRARIES":  {"whole_static_libs", bpparser.List},
39	"LOCAL_SYSTEM_SHARED_LIBRARIES": {"system_shared_libs", bpparser.List},
40	"LOCAL_ASFLAGS":                 {"asflags", bpparser.List},
41	"LOCAL_CLANG_ASFLAGS":           {"clang_asflags", bpparser.List},
42	"LOCAL_CFLAGS":                  {"cflags", bpparser.List},
43	"LOCAL_CONLYFLAGS":              {"conlyflags", bpparser.List},
44	"LOCAL_CPPFLAGS":                {"cppflags", bpparser.List},
45	"LOCAL_LDFLAGS":                 {"ldflags", bpparser.List},
46	"LOCAL_REQUIRED_MODULES":        {"required", bpparser.List},
47	"LOCAL_MODULE_TAGS":             {"tags", bpparser.List},
48	"LOCAL_LDLIBS":                  {"host_ldlibs", bpparser.List},
49	"LOCAL_CLANG_CFLAGS":            {"clang_cflags", bpparser.List},
50	"LOCAL_YACCFLAGS":               {"yaccflags", bpparser.List},
51	"LOCAL_SANITIZE":                {"sanitize", bpparser.List},
52	"LOCAL_SANITIZE_RECOVER":        {"sanitize_recover", bpparser.List},
53
54	"LOCAL_JAVA_RESOURCE_DIRS":    {"java_resource_dirs", bpparser.List},
55	"LOCAL_JAVACFLAGS":            {"javacflags", bpparser.List},
56	"LOCAL_DX_FLAGS":              {"dxflags", bpparser.List},
57	"LOCAL_JAVA_LIBRARIES":        {"java_libs", bpparser.List},
58	"LOCAL_STATIC_JAVA_LIBRARIES": {"java_static_libs", bpparser.List},
59	"LOCAL_AIDL_INCLUDES":         {"aidl_includes", bpparser.List},
60	"LOCAL_AAPT_FLAGS":            {"aaptflags", bpparser.List},
61	"LOCAL_PACKAGE_SPLITS":        {"package_splits", bpparser.List},
62
63	// Bool properties
64	"LOCAL_IS_HOST_MODULE":          {"host", bpparser.Bool},
65	"LOCAL_CLANG":                   {"clang", bpparser.Bool},
66	"LOCAL_FORCE_STATIC_EXECUTABLE": {"static", bpparser.Bool},
67	"LOCAL_NATIVE_COVERAGE":         {"native_coverage", bpparser.Bool},
68	"LOCAL_NO_CRT":                  {"nocrt", bpparser.Bool},
69	"LOCAL_ALLOW_UNDEFINED_SYMBOLS": {"allow_undefined_symbols", bpparser.Bool},
70	"LOCAL_RTTI_FLAG":               {"rtti", bpparser.Bool},
71
72	"LOCAL_NO_STANDARD_LIBRARIES": {"no_standard_libraries", bpparser.Bool},
73
74	"LOCAL_EXPORT_PACKAGE_RESOURCES": {"export_package_resources", bpparser.Bool},
75}
76
77var rewriteProperties = map[string]struct {
78	f func(file *bpFile, prefix string, value *mkparser.MakeString, append bool) error
79}{
80	"LOCAL_C_INCLUDES":            {localIncludeDirs},
81	"LOCAL_EXPORT_C_INCLUDE_DIRS": {exportIncludeDirs},
82	"LOCAL_MODULE_STEM":           {stem},
83	"LOCAL_MODULE_HOST_OS":        {hostOs},
84}
85
86func localAbsPath(value bpparser.Value) (*bpparser.Value, error) {
87	if value.Type != bpparser.String {
88		return nil, fmt.Errorf("isLocalAbsPath expected a string, got %d", value.Type)
89	}
90
91	if value.Expression == nil {
92		if value.Variable == "LOCAL_PATH" {
93			return &bpparser.Value{
94				Type:        bpparser.String,
95				StringValue: ".",
96			}, nil
97		}
98		return nil, nil
99	}
100
101	if value.Expression.Operator != '+' {
102		return nil, nil
103	}
104
105	firstOperand := value.Expression.Args[0]
106	secondOperand := value.Expression.Args[1]
107	if firstOperand.Type != bpparser.String {
108		return nil, nil
109	}
110
111	if firstOperand.Expression != nil {
112		return nil, nil
113	}
114
115	if firstOperand.Variable != "LOCAL_PATH" {
116		return nil, nil
117	}
118
119	if secondOperand.Expression == nil && secondOperand.Variable == "" {
120		if strings.HasPrefix(secondOperand.StringValue, "/") {
121			secondOperand.StringValue = secondOperand.StringValue[1:]
122		}
123	}
124	return &secondOperand, nil
125}
126
127func emptyList(value *bpparser.Value) bool {
128	return value.Type == bpparser.List && value.Expression == nil && value.Variable == "" &&
129		len(value.ListValue) == 0
130}
131
132func splitLocalGlobal(file *bpFile, val *bpparser.Value) (local, global *bpparser.Value, err error) {
133	local = &bpparser.Value{
134		Type: bpparser.List,
135	}
136	global = &bpparser.Value{
137		Type: bpparser.List,
138	}
139
140	if val.Expression != nil {
141		localA, globalA, err := splitLocalGlobal(file, &val.Expression.Args[0])
142		if err != nil {
143			return nil, nil, err
144		}
145
146		localB, globalB, err := splitLocalGlobal(file, &val.Expression.Args[1])
147		if err != nil {
148			return nil, nil, err
149		}
150
151		if emptyList(localA) {
152			local = localB
153		} else if emptyList(localB) {
154			local = localA
155		} else {
156			localExpression := *val.Expression
157			local.Expression = &localExpression
158			local.Expression.Args = [2]bpparser.Value{*localA, *localB}
159		}
160
161		if emptyList(globalA) {
162			global = globalB
163		} else if emptyList(globalB) {
164			global = globalA
165		} else {
166			globalExpression := *val.Expression
167			global.Expression = &globalExpression
168			global.Expression.Args = [2]bpparser.Value{*globalA, *globalB}
169		}
170	} else if val.Variable != "" {
171		if val.Variable == "LOCAL_PATH" {
172			local.ListValue = append(local.ListValue, bpparser.Value{
173				Type:        bpparser.String,
174				StringValue: ".",
175			})
176		} else {
177			global.Variable = val.Variable
178		}
179	} else {
180		for _, v := range val.ListValue {
181			localPath, err := localAbsPath(v)
182			if err != nil {
183				return nil, nil, err
184			}
185			if localPath != nil {
186				local.ListValue = append(local.ListValue, *localPath)
187			} else {
188				global.ListValue = append(global.ListValue, v)
189			}
190		}
191	}
192
193	return local, global, nil
194}
195
196func localIncludeDirs(file *bpFile, prefix string, value *mkparser.MakeString, appendVariable bool) error {
197	val, err := makeVariableToBlueprint(file, value, bpparser.List)
198	if err != nil {
199		return err
200	}
201
202	local, global, err := splitLocalGlobal(file, val)
203	if err != nil {
204		return err
205	}
206
207	if len(global.ListValue) > 0 || global.Expression != nil || global.Variable != "" {
208		err = setVariable(file, appendVariable, prefix, "include_dirs", global, true)
209		if err != nil {
210			return err
211		}
212	}
213
214	if len(local.ListValue) > 0 || local.Expression != nil || local.Variable != "" {
215		err = setVariable(file, appendVariable, prefix, "local_include_dirs", local, true)
216		if err != nil {
217			return err
218		}
219	}
220
221	return nil
222}
223
224func exportIncludeDirs(file *bpFile, prefix string, value *mkparser.MakeString, appendVariable bool) error {
225	val, err := makeVariableToBlueprint(file, value, bpparser.List)
226	if err != nil {
227		return err
228	}
229
230	local, global, err := splitLocalGlobal(file, val)
231	if err != nil {
232		return err
233	}
234
235	if len(local.ListValue) > 0 || local.Expression != nil || local.Variable != "" {
236		err = setVariable(file, appendVariable, prefix, "export_include_dirs", local, true)
237		if err != nil {
238			return err
239		}
240		appendVariable = true
241	}
242
243	// Add any paths that could not be converted to local relative paths to export_include_dirs
244	// anyways, they will cause an error if they don't exist and can be fixed manually.
245	if len(global.ListValue) > 0 || global.Expression != nil || global.Variable != "" {
246		err = setVariable(file, appendVariable, prefix, "export_include_dirs", global, true)
247		if err != nil {
248			return err
249		}
250	}
251
252	return nil
253}
254
255func stem(file *bpFile, prefix string, value *mkparser.MakeString, appendVariable bool) error {
256	val, err := makeVariableToBlueprint(file, value, bpparser.String)
257	if err != nil {
258		return err
259	}
260	varName := "stem"
261
262	if val.Expression != nil && val.Expression.Operator == '+' &&
263		val.Expression.Args[0].Variable == "LOCAL_MODULE" {
264		varName = "suffix"
265		val = &val.Expression.Args[1]
266	}
267
268	return setVariable(file, appendVariable, prefix, varName, val, true)
269}
270
271func hostOs(file *bpFile, prefix string, value *mkparser.MakeString, appendVariable bool) error {
272	val, err := makeVariableToBlueprint(file, value, bpparser.List)
273	if err != nil {
274		return err
275	}
276
277	inList := func(s string) bool {
278		for _, v := range val.ListValue {
279			if v.StringValue == s {
280				return true
281			}
282		}
283		return false
284	}
285
286	falseValue := &bpparser.Value{
287		Type:      bpparser.Bool,
288		BoolValue: false,
289	}
290
291	trueValue := &bpparser.Value{
292		Type:      bpparser.Bool,
293		BoolValue: true,
294	}
295
296	if inList("windows") {
297		err = setVariable(file, appendVariable, "target.windows", "enabled", trueValue, true)
298	}
299
300	if !inList("linux") && err == nil {
301		err = setVariable(file, appendVariable, "target.linux", "enabled", falseValue, true)
302	}
303
304	if !inList("darwin") && err == nil {
305		err = setVariable(file, appendVariable, "target.darwin", "enabled", falseValue, true)
306	}
307
308	return err
309}
310
311var deleteProperties = map[string]struct{}{
312	"LOCAL_CPP_EXTENSION": struct{}{},
313}
314
315var propertyPrefixes = map[string]string{
316	"arm":    "arch.arm",
317	"arm64":  "arm.arm64",
318	"mips":   "arch.mips",
319	"mips64": "arch.mips64",
320	"x86":    "arch.x86",
321	"x86_64": "arch.x86_64",
322	"32":     "multilib.lib32",
323	"64":     "multilib.lib64",
324}
325
326var conditionalTranslations = map[string]map[bool]string{
327	"($(HOST_OS),darwin)": {
328		true:  "target.darwin",
329		false: "target.not_darwin"},
330	"($(HOST_OS), darwin)": {
331		true:  "target.darwin",
332		false: "target.not_darwin"},
333	"($(HOST_OS),windows)": {
334		true:  "target.windows",
335		false: "target.not_windows"},
336	"($(HOST_OS), windows)": {
337		true:  "target.windows",
338		false: "target.not_windows"},
339	"($(HOST_OS),linux)": {
340		true:  "target.linux",
341		false: "target.not_linux"},
342	"($(HOST_OS), linux)": {
343		true:  "target.linux",
344		false: "target.not_linux"},
345	"($(BUILD_OS),darwin)": {
346		true:  "target.darwin",
347		false: "target.not_darwin"},
348	"($(BUILD_OS), darwin)": {
349		true:  "target.darwin",
350		false: "target.not_darwin"},
351	"($(BUILD_OS),linux)": {
352		true:  "target.linux",
353		false: "target.not_linux"},
354	"($(BUILD_OS), linux)": {
355		true:  "target.linux",
356		false: "target.not_linux"},
357	"USE_MINGW": {
358		true:  "target.windows",
359		false: "target.not_windows"},
360	"(,$(TARGET_BUILD_APPS))": {
361		false: "product_variables.unbundled_build",
362	},
363}
364
365func mydir(args []string) string {
366	return "."
367}
368
369func allJavaFilesUnder(args []string) string {
370	dir := ""
371	if len(args) > 0 {
372		dir = strings.TrimSpace(args[0])
373	}
374
375	return fmt.Sprintf("%s/**/*.java", dir)
376}
377
378func allSubdirJavaFiles(args []string) string {
379	return "**/*.java"
380}
381
382var moduleTypes = map[string]string{
383	"BUILD_SHARED_LIBRARY":        "cc_library_shared",
384	"BUILD_STATIC_LIBRARY":        "cc_library_static",
385	"BUILD_HOST_SHARED_LIBRARY":   "cc_library_host_shared",
386	"BUILD_HOST_STATIC_LIBRARY":   "cc_library_host_static",
387	"BUILD_EXECUTABLE":            "cc_binary",
388	"BUILD_HOST_EXECUTABLE":       "cc_binary_host",
389	"BUILD_NATIVE_TEST":           "cc_test",
390	"BUILD_HOST_NATIVE_TEST":      "cc_test_host",
391	"BUILD_NATIVE_BENCHMARK":      "cc_benchmark",
392	"BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host",
393
394	"BUILD_JAVA_LIBRARY":             "java_library",
395	"BUILD_STATIC_JAVA_LIBRARY":      "java_library_static",
396	"BUILD_HOST_JAVA_LIBRARY":        "java_library_host",
397	"BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
398	"BUILD_PACKAGE":                  "android_app",
399
400	"BUILD_PREBUILT": "prebuilt",
401}
402
403var soongModuleTypes = map[string]bool{}
404
405func androidScope() mkparser.Scope {
406	globalScope := mkparser.NewScope(nil)
407	globalScope.Set("CLEAR_VARS", clear_vars)
408	globalScope.SetFunc("my-dir", mydir)
409	globalScope.SetFunc("all-java-files-under", allJavaFilesUnder)
410	globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles)
411
412	for k, v := range moduleTypes {
413		globalScope.Set(k, v)
414		soongModuleTypes[v] = true
415	}
416
417	return globalScope
418}
419