xref: /aosp_15_r20/build/soong/cc/ccdeps.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage cc
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"encoding/json"
19*333d2b36SAndroid Build Coastguard Worker	"fmt"
20*333d2b36SAndroid Build Coastguard Worker	"path"
21*333d2b36SAndroid Build Coastguard Worker	"sort"
22*333d2b36SAndroid Build Coastguard Worker	"strings"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
25*333d2b36SAndroid Build Coastguard Worker)
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Worker// This singleton collects cc modules' source and flags into to a json file.
28*333d2b36SAndroid Build Coastguard Worker// It does so for generating CMakeLists.txt project files needed data when
29*333d2b36SAndroid Build Coastguard Worker// either make, mm, mma, mmm or mmma is called.
30*333d2b36SAndroid Build Coastguard Worker// The info file is generated in $OUT/module_bp_cc_depend.json.
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Workerfunc init() {
33*333d2b36SAndroid Build Coastguard Worker	android.RegisterParallelSingletonType("ccdeps_generator", ccDepsGeneratorSingleton)
34*333d2b36SAndroid Build Coastguard Worker}
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Workerfunc ccDepsGeneratorSingleton() android.Singleton {
37*333d2b36SAndroid Build Coastguard Worker	return &ccdepsGeneratorSingleton{}
38*333d2b36SAndroid Build Coastguard Worker}
39*333d2b36SAndroid Build Coastguard Worker
40*333d2b36SAndroid Build Coastguard Workertype ccdepsGeneratorSingleton struct {
41*333d2b36SAndroid Build Coastguard Worker	outputPath android.Path
42*333d2b36SAndroid Build Coastguard Worker}
43*333d2b36SAndroid Build Coastguard Worker
44*333d2b36SAndroid Build Coastguard Workervar _ android.SingletonMakeVarsProvider = (*ccdepsGeneratorSingleton)(nil)
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Workerconst (
47*333d2b36SAndroid Build Coastguard Worker	ccdepsJsonFileName = "module_bp_cc_deps.json"
48*333d2b36SAndroid Build Coastguard Worker	cClang             = "clang"
49*333d2b36SAndroid Build Coastguard Worker	cppClang           = "clang++"
50*333d2b36SAndroid Build Coastguard Worker)
51*333d2b36SAndroid Build Coastguard Worker
52*333d2b36SAndroid Build Coastguard Workertype ccIdeInfo struct {
53*333d2b36SAndroid Build Coastguard Worker	Path                 []string     `json:"path,omitempty"`
54*333d2b36SAndroid Build Coastguard Worker	Srcs                 []string     `json:"srcs,omitempty"`
55*333d2b36SAndroid Build Coastguard Worker	Global_Common_Flags  ccParameters `json:"global_common_flags,omitempty"`
56*333d2b36SAndroid Build Coastguard Worker	Local_Common_Flags   ccParameters `json:"local_common_flags,omitempty"`
57*333d2b36SAndroid Build Coastguard Worker	Global_C_flags       ccParameters `json:"global_c_flags,omitempty"`
58*333d2b36SAndroid Build Coastguard Worker	Local_C_flags        ccParameters `json:"local_c_flags,omitempty"`
59*333d2b36SAndroid Build Coastguard Worker	Global_C_only_flags  ccParameters `json:"global_c_only_flags,omitempty"`
60*333d2b36SAndroid Build Coastguard Worker	Local_C_only_flags   ccParameters `json:"local_c_only_flags,omitempty"`
61*333d2b36SAndroid Build Coastguard Worker	Global_Cpp_flags     ccParameters `json:"global_cpp_flags,omitempty"`
62*333d2b36SAndroid Build Coastguard Worker	Local_Cpp_flags      ccParameters `json:"local_cpp_flags,omitempty"`
63*333d2b36SAndroid Build Coastguard Worker	System_include_flags ccParameters `json:"system_include_flags,omitempty"`
64*333d2b36SAndroid Build Coastguard Worker	Module_name          string       `json:"module_name,omitempty"`
65*333d2b36SAndroid Build Coastguard Worker}
66*333d2b36SAndroid Build Coastguard Worker
67*333d2b36SAndroid Build Coastguard Workertype ccParameters struct {
68*333d2b36SAndroid Build Coastguard Worker	HeaderSearchPath       []string          `json:"header_search_path,omitempty"`
69*333d2b36SAndroid Build Coastguard Worker	SystemHeaderSearchPath []string          `json:"system_search_path,omitempty"`
70*333d2b36SAndroid Build Coastguard Worker	FlagParameters         []string          `json:"flag,omitempty"`
71*333d2b36SAndroid Build Coastguard Worker	SysRoot                string            `json:"system_root,omitempty"`
72*333d2b36SAndroid Build Coastguard Worker	RelativeFilePathFlags  map[string]string `json:"relative_file_path,omitempty"`
73*333d2b36SAndroid Build Coastguard Worker}
74*333d2b36SAndroid Build Coastguard Worker
75*333d2b36SAndroid Build Coastguard Workertype ccMapIdeInfos map[string]ccIdeInfo
76*333d2b36SAndroid Build Coastguard Worker
77*333d2b36SAndroid Build Coastguard Workertype ccDeps struct {
78*333d2b36SAndroid Build Coastguard Worker	C_clang   string        `json:"clang,omitempty"`
79*333d2b36SAndroid Build Coastguard Worker	Cpp_clang string        `json:"clang++,omitempty"`
80*333d2b36SAndroid Build Coastguard Worker	Modules   ccMapIdeInfos `json:"modules,omitempty"`
81*333d2b36SAndroid Build Coastguard Worker}
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Workerfunc (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
84*333d2b36SAndroid Build Coastguard Worker	// (b/204397180) Generate module_bp_cc_deps.json by default.
85*333d2b36SAndroid Build Coastguard Worker	moduleDeps := ccDeps{}
86*333d2b36SAndroid Build Coastguard Worker	moduleInfos := map[string]ccIdeInfo{}
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	// Track if best variant (device arch match) has been found.
89*333d2b36SAndroid Build Coastguard Worker	bestVariantFound := map[string]bool{}
90*333d2b36SAndroid Build Coastguard Worker
91*333d2b36SAndroid Build Coastguard Worker	pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
92*333d2b36SAndroid Build Coastguard Worker	moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang)
93*333d2b36SAndroid Build Coastguard Worker	moduleDeps.Cpp_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cppClang)
94*333d2b36SAndroid Build Coastguard Worker
95*333d2b36SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(module android.Module) {
96*333d2b36SAndroid Build Coastguard Worker		if ccModule, ok := module.(*Module); ok {
97*333d2b36SAndroid Build Coastguard Worker			if compiledModule, ok := ccModule.compiler.(CompiledInterface); ok {
98*333d2b36SAndroid Build Coastguard Worker				generateCLionProjectData(ctx, compiledModule, ccModule, bestVariantFound, moduleInfos)
99*333d2b36SAndroid Build Coastguard Worker			}
100*333d2b36SAndroid Build Coastguard Worker		}
101*333d2b36SAndroid Build Coastguard Worker	})
102*333d2b36SAndroid Build Coastguard Worker
103*333d2b36SAndroid Build Coastguard Worker	moduleDeps.Modules = moduleInfos
104*333d2b36SAndroid Build Coastguard Worker
105*333d2b36SAndroid Build Coastguard Worker	ccfpath := android.PathForOutput(ctx, ccdepsJsonFileName)
106*333d2b36SAndroid Build Coastguard Worker	err := createJsonFile(moduleDeps, ccfpath)
107*333d2b36SAndroid Build Coastguard Worker	if err != nil {
108*333d2b36SAndroid Build Coastguard Worker		ctx.Errorf(err.Error())
109*333d2b36SAndroid Build Coastguard Worker	}
110*333d2b36SAndroid Build Coastguard Worker	c.outputPath = ccfpath
111*333d2b36SAndroid Build Coastguard Worker
112*333d2b36SAndroid Build Coastguard Worker	// This is necessary to satisfy the dangling rules check as this file is written by Soong rather than a rule.
113*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, android.BuildParams{
114*333d2b36SAndroid Build Coastguard Worker		Rule:   android.Touch,
115*333d2b36SAndroid Build Coastguard Worker		Output: ccfpath,
116*333d2b36SAndroid Build Coastguard Worker	})
117*333d2b36SAndroid Build Coastguard Worker}
118*333d2b36SAndroid Build Coastguard Worker
119*333d2b36SAndroid Build Coastguard Workerfunc (c *ccdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) {
120*333d2b36SAndroid Build Coastguard Worker	if c.outputPath == nil {
121*333d2b36SAndroid Build Coastguard Worker		return
122*333d2b36SAndroid Build Coastguard Worker	}
123*333d2b36SAndroid Build Coastguard Worker
124*333d2b36SAndroid Build Coastguard Worker	ctx.DistForGoal("general-tests", c.outputPath)
125*333d2b36SAndroid Build Coastguard Worker}
126*333d2b36SAndroid Build Coastguard Worker
127*333d2b36SAndroid Build Coastguard Workerfunc parseCompilerCCParameters(ctx android.SingletonContext, params []string) ccParameters {
128*333d2b36SAndroid Build Coastguard Worker	compilerParams := ccParameters{}
129*333d2b36SAndroid Build Coastguard Worker
130*333d2b36SAndroid Build Coastguard Worker	cparams := []string{}
131*333d2b36SAndroid Build Coastguard Worker	for _, param := range params {
132*333d2b36SAndroid Build Coastguard Worker		param, _ = evalVariable(ctx, param)
133*333d2b36SAndroid Build Coastguard Worker		cparams = append(cparams, param)
134*333d2b36SAndroid Build Coastguard Worker	}
135*333d2b36SAndroid Build Coastguard Worker
136*333d2b36SAndroid Build Coastguard Worker	// Soong does not guarantee that each flag will be in an individual string. e.g: The
137*333d2b36SAndroid Build Coastguard Worker	// input received could be:
138*333d2b36SAndroid Build Coastguard Worker	// params = {"-isystem", "path/to/system"}
139*333d2b36SAndroid Build Coastguard Worker	// or it could be
140*333d2b36SAndroid Build Coastguard Worker	// params = {"-isystem path/to/system"}
141*333d2b36SAndroid Build Coastguard Worker	// To normalize the input, we split all strings with the "space" character and consolidate
142*333d2b36SAndroid Build Coastguard Worker	// all tokens into a flattened parameters list
143*333d2b36SAndroid Build Coastguard Worker	cparams = normalizeParameters(cparams)
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < len(cparams); i++ {
146*333d2b36SAndroid Build Coastguard Worker		param := cparams[i]
147*333d2b36SAndroid Build Coastguard Worker		if param == "" {
148*333d2b36SAndroid Build Coastguard Worker			continue
149*333d2b36SAndroid Build Coastguard Worker		}
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Worker		switch categorizeParameter(param) {
152*333d2b36SAndroid Build Coastguard Worker		case headerSearchPath:
153*333d2b36SAndroid Build Coastguard Worker			compilerParams.HeaderSearchPath =
154*333d2b36SAndroid Build Coastguard Worker				append(compilerParams.HeaderSearchPath, strings.TrimPrefix(param, "-I"))
155*333d2b36SAndroid Build Coastguard Worker		case systemHeaderSearchPath:
156*333d2b36SAndroid Build Coastguard Worker			if i < len(cparams)-1 {
157*333d2b36SAndroid Build Coastguard Worker				compilerParams.SystemHeaderSearchPath = append(compilerParams.SystemHeaderSearchPath, cparams[i+1])
158*333d2b36SAndroid Build Coastguard Worker			}
159*333d2b36SAndroid Build Coastguard Worker			i = i + 1
160*333d2b36SAndroid Build Coastguard Worker		case flag:
161*333d2b36SAndroid Build Coastguard Worker			c := cleanupParameter(param)
162*333d2b36SAndroid Build Coastguard Worker			compilerParams.FlagParameters = append(compilerParams.FlagParameters, c)
163*333d2b36SAndroid Build Coastguard Worker		case systemRoot:
164*333d2b36SAndroid Build Coastguard Worker			if i < len(cparams)-1 {
165*333d2b36SAndroid Build Coastguard Worker				compilerParams.SysRoot = cparams[i+1]
166*333d2b36SAndroid Build Coastguard Worker			}
167*333d2b36SAndroid Build Coastguard Worker			i = i + 1
168*333d2b36SAndroid Build Coastguard Worker		case relativeFilePathFlag:
169*333d2b36SAndroid Build Coastguard Worker			flagComponents := strings.Split(param, "=")
170*333d2b36SAndroid Build Coastguard Worker			if len(flagComponents) == 2 {
171*333d2b36SAndroid Build Coastguard Worker				if compilerParams.RelativeFilePathFlags == nil {
172*333d2b36SAndroid Build Coastguard Worker					compilerParams.RelativeFilePathFlags = map[string]string{}
173*333d2b36SAndroid Build Coastguard Worker				}
174*333d2b36SAndroid Build Coastguard Worker				compilerParams.RelativeFilePathFlags[flagComponents[0]] = flagComponents[1]
175*333d2b36SAndroid Build Coastguard Worker			}
176*333d2b36SAndroid Build Coastguard Worker		}
177*333d2b36SAndroid Build Coastguard Worker	}
178*333d2b36SAndroid Build Coastguard Worker	return compilerParams
179*333d2b36SAndroid Build Coastguard Worker}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Workerfunc generateCLionProjectData(ctx android.SingletonContext, compiledModule CompiledInterface,
182*333d2b36SAndroid Build Coastguard Worker	ccModule *Module, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) {
183*333d2b36SAndroid Build Coastguard Worker	moduleName := ccModule.ModuleBase.Name()
184*333d2b36SAndroid Build Coastguard Worker	srcs := compiledModule.Srcs()
185*333d2b36SAndroid Build Coastguard Worker
186*333d2b36SAndroid Build Coastguard Worker	// Skip if best variant has already been found.
187*333d2b36SAndroid Build Coastguard Worker	if bestVariantFound[moduleName] {
188*333d2b36SAndroid Build Coastguard Worker		return
189*333d2b36SAndroid Build Coastguard Worker	}
190*333d2b36SAndroid Build Coastguard Worker
191*333d2b36SAndroid Build Coastguard Worker	// Skip if sources are empty.
192*333d2b36SAndroid Build Coastguard Worker	if len(srcs) == 0 {
193*333d2b36SAndroid Build Coastguard Worker		return
194*333d2b36SAndroid Build Coastguard Worker	}
195*333d2b36SAndroid Build Coastguard Worker
196*333d2b36SAndroid Build Coastguard Worker	// Check if device arch matches, in which case this is the best variant and takes precedence.
197*333d2b36SAndroid Build Coastguard Worker	if ccModule.Device() && ccModule.ModuleBase.Arch().ArchType.Name == ctx.DeviceConfig().DeviceArch() {
198*333d2b36SAndroid Build Coastguard Worker		bestVariantFound[moduleName] = true
199*333d2b36SAndroid Build Coastguard Worker	} else if _, ok := moduleInfos[moduleName]; ok {
200*333d2b36SAndroid Build Coastguard Worker		// Skip because this isn't the best variant and a previous one has already been added.
201*333d2b36SAndroid Build Coastguard Worker		// Heuristically, ones that appear first are likely to be more relevant.
202*333d2b36SAndroid Build Coastguard Worker		return
203*333d2b36SAndroid Build Coastguard Worker	}
204*333d2b36SAndroid Build Coastguard Worker
205*333d2b36SAndroid Build Coastguard Worker	dpInfo := ccIdeInfo{}
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker	dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(ccModule)))
208*333d2b36SAndroid Build Coastguard Worker	dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...)
209*333d2b36SAndroid Build Coastguard Worker	dpInfo.Path = android.FirstUniqueStrings(dpInfo.Path)
210*333d2b36SAndroid Build Coastguard Worker	dpInfo.Srcs = android.FirstUniqueStrings(dpInfo.Srcs)
211*333d2b36SAndroid Build Coastguard Worker
212*333d2b36SAndroid Build Coastguard Worker	dpInfo.Global_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CommonFlags)
213*333d2b36SAndroid Build Coastguard Worker	dpInfo.Local_Common_Flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CommonFlags)
214*333d2b36SAndroid Build Coastguard Worker	dpInfo.Global_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CFlags)
215*333d2b36SAndroid Build Coastguard Worker	dpInfo.Local_C_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CFlags)
216*333d2b36SAndroid Build Coastguard Worker	dpInfo.Global_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.ConlyFlags)
217*333d2b36SAndroid Build Coastguard Worker	dpInfo.Local_C_only_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.ConlyFlags)
218*333d2b36SAndroid Build Coastguard Worker	dpInfo.Global_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Global.CppFlags)
219*333d2b36SAndroid Build Coastguard Worker	dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.flags.Local.CppFlags)
220*333d2b36SAndroid Build Coastguard Worker	dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.flags.SystemIncludeFlags)
221*333d2b36SAndroid Build Coastguard Worker
222*333d2b36SAndroid Build Coastguard Worker	dpInfo.Module_name = moduleName
223*333d2b36SAndroid Build Coastguard Worker
224*333d2b36SAndroid Build Coastguard Worker	moduleInfos[moduleName] = dpInfo
225*333d2b36SAndroid Build Coastguard Worker}
226*333d2b36SAndroid Build Coastguard Worker
227*333d2b36SAndroid Build Coastguard Workertype Deal struct {
228*333d2b36SAndroid Build Coastguard Worker	Name    string
229*333d2b36SAndroid Build Coastguard Worker	ideInfo ccIdeInfo
230*333d2b36SAndroid Build Coastguard Worker}
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Workertype Deals []Deal
233*333d2b36SAndroid Build Coastguard Worker
234*333d2b36SAndroid Build Coastguard Worker// Ensure it satisfies sort.Interface
235*333d2b36SAndroid Build Coastguard Workerfunc (d Deals) Len() int           { return len(d) }
236*333d2b36SAndroid Build Coastguard Workerfunc (d Deals) Less(i, j int) bool { return d[i].Name < d[j].Name }
237*333d2b36SAndroid Build Coastguard Workerfunc (d Deals) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }
238*333d2b36SAndroid Build Coastguard Worker
239*333d2b36SAndroid Build Coastguard Workerfunc sortMap(moduleInfos map[string]ccIdeInfo) map[string]ccIdeInfo {
240*333d2b36SAndroid Build Coastguard Worker	var deals Deals
241*333d2b36SAndroid Build Coastguard Worker	for k, v := range moduleInfos {
242*333d2b36SAndroid Build Coastguard Worker		deals = append(deals, Deal{k, v})
243*333d2b36SAndroid Build Coastguard Worker	}
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Worker	sort.Sort(deals)
246*333d2b36SAndroid Build Coastguard Worker
247*333d2b36SAndroid Build Coastguard Worker	m := map[string]ccIdeInfo{}
248*333d2b36SAndroid Build Coastguard Worker	for _, d := range deals {
249*333d2b36SAndroid Build Coastguard Worker		m[d.Name] = d.ideInfo
250*333d2b36SAndroid Build Coastguard Worker	}
251*333d2b36SAndroid Build Coastguard Worker	return m
252*333d2b36SAndroid Build Coastguard Worker}
253*333d2b36SAndroid Build Coastguard Worker
254*333d2b36SAndroid Build Coastguard Workerfunc createJsonFile(moduleDeps ccDeps, ccfpath android.WritablePath) error {
255*333d2b36SAndroid Build Coastguard Worker	buf, err := json.MarshalIndent(moduleDeps, "", "\t")
256*333d2b36SAndroid Build Coastguard Worker	if err != nil {
257*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf("JSON marshal of cc deps failed: %s", err)
258*333d2b36SAndroid Build Coastguard Worker	}
259*333d2b36SAndroid Build Coastguard Worker	err = android.WriteFileToOutputDir(ccfpath, buf, 0666)
260*333d2b36SAndroid Build Coastguard Worker	if err != nil {
261*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf("Writing cc deps to %s failed: %s", ccfpath.String(), err)
262*333d2b36SAndroid Build Coastguard Worker	}
263*333d2b36SAndroid Build Coastguard Worker	return nil
264*333d2b36SAndroid Build Coastguard Worker}
265