xref: /aosp_15_r20/build/soong/partner/bpfix/extensions/headers.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Workerpackage extensions
2*333d2b36SAndroid Build Coastguard Worker
3*333d2b36SAndroid Build Coastguard Workerimport (
4*333d2b36SAndroid Build Coastguard Worker	"strings"
5*333d2b36SAndroid Build Coastguard Worker
6*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/parser"
7*333d2b36SAndroid Build Coastguard Worker
8*333d2b36SAndroid Build Coastguard Worker	"android/soong/bpfix/bpfix"
9*333d2b36SAndroid Build Coastguard Worker)
10*333d2b36SAndroid Build Coastguard Worker
11*333d2b36SAndroid Build Coastguard Workervar fixSteps = bpfix.FixStepsExtension{
12*333d2b36SAndroid Build Coastguard Worker	Name: "partner-include-dirs",
13*333d2b36SAndroid Build Coastguard Worker	Steps: []bpfix.FixStep{
14*333d2b36SAndroid Build Coastguard Worker		{
15*333d2b36SAndroid Build Coastguard Worker			Name: "fixIncludeDirs",
16*333d2b36SAndroid Build Coastguard Worker			Fix:  fixIncludeDirs,
17*333d2b36SAndroid Build Coastguard Worker		},
18*333d2b36SAndroid Build Coastguard Worker	},
19*333d2b36SAndroid Build Coastguard Worker}
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Workerfunc init() {
22*333d2b36SAndroid Build Coastguard Worker	bpfix.RegisterFixStepExtension(&fixSteps)
23*333d2b36SAndroid Build Coastguard Worker}
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Workertype includeDirFix struct {
26*333d2b36SAndroid Build Coastguard Worker	libName  string
27*333d2b36SAndroid Build Coastguard Worker	libType  string
28*333d2b36SAndroid Build Coastguard Worker	variable string
29*333d2b36SAndroid Build Coastguard Worker	subdir   string
30*333d2b36SAndroid Build Coastguard Worker}
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Workervar commonIncludeDirs = []includeDirFix{
33*333d2b36SAndroid Build Coastguard Worker	{
34*333d2b36SAndroid Build Coastguard Worker		libName:  "my_header_lib",
35*333d2b36SAndroid Build Coastguard Worker		libType:  "header_libs",
36*333d2b36SAndroid Build Coastguard Worker		variable: "TARGET_OUT_HEADERS",
37*333d2b36SAndroid Build Coastguard Worker		subdir:   "/my_headers",
38*333d2b36SAndroid Build Coastguard Worker	},
39*333d2b36SAndroid Build Coastguard Worker}
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Workerfunc findHeaderLib(e parser.Expression) (*includeDirFix, bool) {
42*333d2b36SAndroid Build Coastguard Worker	if op, ok := e.(*parser.Operator); ok {
43*333d2b36SAndroid Build Coastguard Worker		if op.Operator != '+' {
44*333d2b36SAndroid Build Coastguard Worker			return nil, false
45*333d2b36SAndroid Build Coastguard Worker		}
46*333d2b36SAndroid Build Coastguard Worker		arg0, ok := op.Args[0].(*parser.Variable)
47*333d2b36SAndroid Build Coastguard Worker		arg1, ok1 := op.Args[1].(*parser.String)
48*333d2b36SAndroid Build Coastguard Worker		if !ok || !ok1 {
49*333d2b36SAndroid Build Coastguard Worker			return nil, false
50*333d2b36SAndroid Build Coastguard Worker		}
51*333d2b36SAndroid Build Coastguard Worker		for _, lib := range commonIncludeDirs {
52*333d2b36SAndroid Build Coastguard Worker			if arg0.Name == lib.variable && arg1.Value == lib.subdir {
53*333d2b36SAndroid Build Coastguard Worker				return &lib, true
54*333d2b36SAndroid Build Coastguard Worker			}
55*333d2b36SAndroid Build Coastguard Worker		}
56*333d2b36SAndroid Build Coastguard Worker	}
57*333d2b36SAndroid Build Coastguard Worker	return nil, false
58*333d2b36SAndroid Build Coastguard Worker}
59*333d2b36SAndroid Build Coastguard Workerfunc searchThroughOperatorList(mod *parser.Module, e parser.Expression) {
60*333d2b36SAndroid Build Coastguard Worker	if list, ok := e.(*parser.List); ok {
61*333d2b36SAndroid Build Coastguard Worker		newList := make([]parser.Expression, 0, len(list.Values))
62*333d2b36SAndroid Build Coastguard Worker		for _, item := range list.Values {
63*333d2b36SAndroid Build Coastguard Worker			if lib, found := findHeaderLib(item); found {
64*333d2b36SAndroid Build Coastguard Worker				if lib.libName != "" {
65*333d2b36SAndroid Build Coastguard Worker					addLibrary(mod, lib.libType, lib.libName)
66*333d2b36SAndroid Build Coastguard Worker				}
67*333d2b36SAndroid Build Coastguard Worker			} else {
68*333d2b36SAndroid Build Coastguard Worker				newList = append(newList, item)
69*333d2b36SAndroid Build Coastguard Worker			}
70*333d2b36SAndroid Build Coastguard Worker		}
71*333d2b36SAndroid Build Coastguard Worker		list.Values = newList
72*333d2b36SAndroid Build Coastguard Worker	}
73*333d2b36SAndroid Build Coastguard Worker	if op, ok := e.(*parser.Operator); ok {
74*333d2b36SAndroid Build Coastguard Worker		searchThroughOperatorList(mod, op.Args[0])
75*333d2b36SAndroid Build Coastguard Worker		searchThroughOperatorList(mod, op.Args[1])
76*333d2b36SAndroid Build Coastguard Worker	}
77*333d2b36SAndroid Build Coastguard Worker}
78*333d2b36SAndroid Build Coastguard Workerfunc getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
79*333d2b36SAndroid Build Coastguard Worker	prop, ok := mod.GetProperty(name)
80*333d2b36SAndroid Build Coastguard Worker	if !ok {
81*333d2b36SAndroid Build Coastguard Worker		return nil, false
82*333d2b36SAndroid Build Coastguard Worker	}
83*333d2b36SAndroid Build Coastguard Worker	list, ok = prop.Value.(*parser.List)
84*333d2b36SAndroid Build Coastguard Worker	return list, ok
85*333d2b36SAndroid Build Coastguard Worker}
86*333d2b36SAndroid Build Coastguard Workerfunc addLibrary(mod *parser.Module, libType string, libName string) {
87*333d2b36SAndroid Build Coastguard Worker	var list, ok = getLiteralListProperty(mod, libType)
88*333d2b36SAndroid Build Coastguard Worker	if !ok {
89*333d2b36SAndroid Build Coastguard Worker		list = new(parser.List)
90*333d2b36SAndroid Build Coastguard Worker		prop := new(parser.Property)
91*333d2b36SAndroid Build Coastguard Worker		prop.Name = libType
92*333d2b36SAndroid Build Coastguard Worker		prop.Value = list
93*333d2b36SAndroid Build Coastguard Worker		mod.Properties = append(mod.Properties, prop)
94*333d2b36SAndroid Build Coastguard Worker	} else {
95*333d2b36SAndroid Build Coastguard Worker		for _, v := range list.Values {
96*333d2b36SAndroid Build Coastguard Worker			if stringValue, ok := v.(*parser.String); ok && stringValue.Value == libName {
97*333d2b36SAndroid Build Coastguard Worker				return
98*333d2b36SAndroid Build Coastguard Worker			}
99*333d2b36SAndroid Build Coastguard Worker		}
100*333d2b36SAndroid Build Coastguard Worker	}
101*333d2b36SAndroid Build Coastguard Worker	lib := new(parser.String)
102*333d2b36SAndroid Build Coastguard Worker	lib.Value = libName
103*333d2b36SAndroid Build Coastguard Worker	list.Values = append(list.Values, lib)
104*333d2b36SAndroid Build Coastguard Worker}
105*333d2b36SAndroid Build Coastguard Workerfunc fixIncludeDirs(f *bpfix.Fixer) error {
106*333d2b36SAndroid Build Coastguard Worker	tree := f.Tree()
107*333d2b36SAndroid Build Coastguard Worker	for _, def := range tree.Defs {
108*333d2b36SAndroid Build Coastguard Worker		mod, ok := def.(*parser.Module)
109*333d2b36SAndroid Build Coastguard Worker		if !ok {
110*333d2b36SAndroid Build Coastguard Worker			continue
111*333d2b36SAndroid Build Coastguard Worker		}
112*333d2b36SAndroid Build Coastguard Worker		if !strings.HasPrefix(mod.Type, "cc_") {
113*333d2b36SAndroid Build Coastguard Worker			continue
114*333d2b36SAndroid Build Coastguard Worker		}
115*333d2b36SAndroid Build Coastguard Worker		if prop, ok := mod.GetProperty("include_dirs"); ok {
116*333d2b36SAndroid Build Coastguard Worker			searchThroughOperatorList(mod, prop.Value)
117*333d2b36SAndroid Build Coastguard Worker		}
118*333d2b36SAndroid Build Coastguard Worker	}
119*333d2b36SAndroid Build Coastguard Worker	return nil
120*333d2b36SAndroid Build Coastguard Worker}
121