• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 Google Inc. All rights reserved.
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 cc
16
17// This file generates the final rules for compiling all C/C++.  All properties related to
18// compiling should have been translated into builderFlags or another argument to the Transform*
19// functions.
20
21import (
22	"fmt"
23	"path/filepath"
24	"runtime"
25	"strconv"
26	"strings"
27
28	"github.com/google/blueprint"
29
30	"android/soong/android"
31	"android/soong/cc/config"
32)
33
34const (
35	objectExtension        = ".o"
36	staticLibraryExtension = ".a"
37)
38
39var (
40	abiCheckAllowFlags = []string{
41		"-allow-unreferenced-changes",
42		"-allow-unreferenced-elf-symbol-changes",
43	}
44)
45
46var (
47	pctx = android.NewPackageContext("android/soong/cc")
48
49	cc = pctx.AndroidGomaStaticRule("cc",
50		blueprint.RuleParams{
51			Depfile:     "${out}.d",
52			Deps:        blueprint.DepsGCC,
53			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
54			CommandDeps: []string{"$ccCmd"},
55		},
56		"ccCmd", "cFlags")
57
58	ccNoDeps = pctx.AndroidGomaStaticRule("ccNoDeps",
59		blueprint.RuleParams{
60			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -o $out $in",
61			CommandDeps: []string{"$ccCmd"},
62		},
63		"ccCmd", "cFlags")
64
65	ld = pctx.AndroidStaticRule("ld",
66		blueprint.RuleParams{
67			Command: "$ldCmd ${crtBegin} @${out}.rsp " +
68				"${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
69			CommandDeps:    []string{"$ldCmd"},
70			Rspfile:        "${out}.rsp",
71			RspfileContent: "${in}",
72			// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
73			Restat: true,
74		},
75		"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags")
76
77	partialLd = pctx.AndroidStaticRule("partialLd",
78		blueprint.RuleParams{
79			// Without -no-pie, clang 7.0 adds -pie to link Android files,
80			// but -r and -pie cannot be used together.
81			Command:     "$ldCmd -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
82			CommandDeps: []string{"$ldCmd"},
83		},
84		"ldCmd", "ldFlags")
85
86	ar = pctx.AndroidStaticRule("ar",
87		blueprint.RuleParams{
88			Command:        "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
89			CommandDeps:    []string{"$arCmd"},
90			Rspfile:        "${out}.rsp",
91			RspfileContent: "${in}",
92		},
93		"arCmd", "arFlags")
94
95	darwinAr = pctx.AndroidStaticRule("darwinAr",
96		blueprint.RuleParams{
97			Command:     "rm -f ${out} && ${config.MacArPath} $arFlags $out $in",
98			CommandDeps: []string{"${config.MacArPath}"},
99		},
100		"arFlags")
101
102	darwinAppendAr = pctx.AndroidStaticRule("darwinAppendAr",
103		blueprint.RuleParams{
104			Command:     "cp -f ${inAr} ${out}.tmp && ${config.MacArPath} $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}",
105			CommandDeps: []string{"${config.MacArPath}", "${inAr}"},
106		},
107		"arFlags", "inAr")
108
109	darwinStrip = pctx.AndroidStaticRule("darwinStrip",
110		blueprint.RuleParams{
111			Command:     "${config.MacStripPath} -u -r -o $out $in",
112			CommandDeps: []string{"${config.MacStripPath}"},
113		})
114
115	prefixSymbols = pctx.AndroidStaticRule("prefixSymbols",
116		blueprint.RuleParams{
117			Command:     "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
118			CommandDeps: []string{"$objcopyCmd"},
119		},
120		"objcopyCmd", "prefix")
121
122	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
123	_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
124
125	// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
126	// file descriptors on darwin.  Limit concurrent calls to 5 on darwin.
127	darwinStripPool = func() blueprint.Pool {
128		if runtime.GOOS == "darwin" {
129			return pctx.StaticPool("darwinStripPool", blueprint.PoolParams{
130				Depth: 5,
131			})
132		} else {
133			return nil
134		}
135	}()
136
137	strip = pctx.AndroidStaticRule("strip",
138		blueprint.RuleParams{
139			Depfile:     "${out}.d",
140			Deps:        blueprint.DepsGCC,
141			Command:     "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
142			CommandDeps: []string{"$stripPath", "$xzCmd"},
143			Pool:        darwinStripPool,
144		},
145		"args", "crossCompile")
146
147	emptyFile = pctx.AndroidStaticRule("emptyFile",
148		blueprint.RuleParams{
149			Command: "rm -f $out && touch $out",
150		})
151
152	_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
153
154	toc = pctx.AndroidStaticRule("toc",
155		blueprint.RuleParams{
156			Depfile:     "${out}.d",
157			Deps:        blueprint.DepsGCC,
158			Command:     "CROSS_COMPILE=$crossCompile $tocPath $format -i ${in} -o ${out} -d ${out}.d",
159			CommandDeps: []string{"$tocPath"},
160			Restat:      true,
161		},
162		"crossCompile", "format")
163
164	clangTidy = pctx.AndroidStaticRule("clangTidy",
165		blueprint.RuleParams{
166			Command:     "rm -f $out && CLANG_TIDY=${config.ClangBin}/clang-tidy ${config.ClangTidyShellPath} $tidyFlags $in -- $cFlags && touch $out",
167			CommandDeps: []string{"${config.ClangBin}/clang-tidy", "${config.ClangTidyShellPath}"},
168		},
169		"cFlags", "tidyFlags")
170
171	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
172
173	yasm = pctx.AndroidStaticRule("yasm",
174		blueprint.RuleParams{
175			Command:     "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d",
176			CommandDeps: []string{"$yasmCmd"},
177			Depfile:     "$out.d",
178			Deps:        blueprint.DepsGCC,
179		},
180		"asFlags")
181
182	windres = pctx.AndroidStaticRule("windres",
183		blueprint.RuleParams{
184			Command:     "$windresCmd $flags -I$$(dirname $in) -i $in -o $out",
185			CommandDeps: []string{"$windresCmd"},
186		},
187		"windresCmd", "flags")
188
189	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
190
191	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
192	sAbiDump = pctx.AndroidStaticRule("sAbiDump",
193		blueprint.RuleParams{
194			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
195			CommandDeps: []string{"$sAbiDumper"},
196		},
197		"cFlags", "exportDirs")
198
199	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
200
201	sAbiLink = pctx.AndroidStaticRule("sAbiLink",
202		blueprint.RuleParams{
203			Command:        "$sAbiLinker -o ${out} $symbolFilter -arch $arch  $exportedHeaderFlags @${out}.rsp ",
204			CommandDeps:    []string{"$sAbiLinker"},
205			Rspfile:        "${out}.rsp",
206			RspfileContent: "${in}",
207		},
208		"symbolFilter", "arch", "exportedHeaderFlags")
209
210	_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
211
212	sAbiDiff = pctx.AndroidRuleFunc("sAbiDiff",
213		func(ctx android.PackageRuleContext) blueprint.RuleParams {
214			// TODO(b/78139997): Add -check-all-apis back
215			commandStr := "($sAbiDiffer ${allowFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
216			commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'"
217			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
218			commandStr += " && exit 1)"
219			return blueprint.RuleParams{
220				Command:     commandStr,
221				CommandDeps: []string{"$sAbiDiffer"},
222			}
223		},
224		"allowFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
225
226	unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
227		blueprint.RuleParams{
228			Command: "gunzip -c $in > $out",
229		})
230)
231
232func init() {
233	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
234	// debug output. That way two builds in two different directories will
235	// create the same output.
236	if runtime.GOOS != "darwin" {
237		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
238	} else {
239		// Darwin doesn't have /proc
240		pctx.StaticVariable("relPwd", "")
241	}
242}
243
244type builderFlags struct {
245	globalFlags     string
246	arFlags         string
247	asFlags         string
248	cFlags          string
249	toolingCFlags   string // A separate set of cFlags for clang LibTooling tools
250	toolingCppFlags string // A separate set of cppFlags for clang LibTooling tools
251	conlyFlags      string
252	cppFlags        string
253	ldFlags         string
254	libFlags        string
255	yaccFlags       string
256	tidyFlags       string
257	sAbiFlags       string
258	yasmFlags       string
259	aidlFlags       string
260	rsFlags         string
261	toolchain       config.Toolchain
262	tidy            bool
263	coverage        bool
264	sAbiDump        bool
265
266	systemIncludeFlags string
267
268	groupStaticLibs bool
269
270	stripKeepSymbols       bool
271	stripKeepSymbolsList   string
272	stripKeepMiniDebugInfo bool
273	stripAddGnuDebuglink   bool
274	stripUseGnuStrip       bool
275
276	proto            android.ProtoFlags
277	protoC           bool
278	protoOptionsFile bool
279}
280
281type Objects struct {
282	objFiles      android.Paths
283	tidyFiles     android.Paths
284	coverageFiles android.Paths
285	sAbiDumpFiles android.Paths
286}
287
288func (a Objects) Copy() Objects {
289	return Objects{
290		objFiles:      append(android.Paths{}, a.objFiles...),
291		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
292		coverageFiles: append(android.Paths{}, a.coverageFiles...),
293		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
294	}
295}
296
297func (a Objects) Append(b Objects) Objects {
298	return Objects{
299		objFiles:      append(a.objFiles, b.objFiles...),
300		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
301		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
302		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
303	}
304}
305
306// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
307func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths,
308	flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
309
310	objFiles := make(android.Paths, len(srcFiles))
311	var tidyFiles android.Paths
312	if flags.tidy {
313		tidyFiles = make(android.Paths, 0, len(srcFiles))
314	}
315	var coverageFiles android.Paths
316	if flags.coverage {
317		coverageFiles = make(android.Paths, 0, len(srcFiles))
318	}
319
320	commonFlags := strings.Join([]string{
321		flags.globalFlags,
322		flags.systemIncludeFlags,
323	}, " ")
324
325	toolingCflags := strings.Join([]string{
326		commonFlags,
327		flags.toolingCFlags,
328		flags.conlyFlags,
329	}, " ")
330
331	cflags := strings.Join([]string{
332		commonFlags,
333		flags.cFlags,
334		flags.conlyFlags,
335	}, " ")
336
337	toolingCppflags := strings.Join([]string{
338		commonFlags,
339		flags.toolingCFlags,
340		flags.toolingCppFlags,
341	}, " ")
342
343	cppflags := strings.Join([]string{
344		commonFlags,
345		flags.cFlags,
346		flags.cppFlags,
347	}, " ")
348
349	asflags := strings.Join([]string{
350		commonFlags,
351		flags.asFlags,
352	}, " ")
353
354	var sAbiDumpFiles android.Paths
355	if flags.sAbiDump {
356		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
357	}
358
359	cflags += " ${config.NoOverrideClangGlobalCflags}"
360	toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
361	cppflags += " ${config.NoOverrideClangGlobalCflags}"
362	toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
363
364	for i, srcFile := range srcFiles {
365		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
366
367		objFiles[i] = objFile
368
369		switch srcFile.Ext() {
370		case ".asm":
371			ctx.Build(pctx, android.BuildParams{
372				Rule:        yasm,
373				Description: "yasm " + srcFile.Rel(),
374				Output:      objFile,
375				Input:       srcFile,
376				Implicits:   cFlagsDeps,
377				OrderOnly:   pathDeps,
378				Args: map[string]string{
379					"asFlags": flags.yasmFlags,
380				},
381			})
382			continue
383		case ".rc":
384			ctx.Build(pctx, android.BuildParams{
385				Rule:        windres,
386				Description: "windres " + srcFile.Rel(),
387				Output:      objFile,
388				Input:       srcFile,
389				Implicits:   cFlagsDeps,
390				OrderOnly:   pathDeps,
391				Args: map[string]string{
392					"windresCmd": gccCmd(flags.toolchain, "windres"),
393					"flags":      flags.toolchain.WindresFlags(),
394				},
395			})
396			continue
397		}
398
399		var moduleCflags string
400		var moduleToolingCflags string
401		var ccCmd string
402		tidy := flags.tidy
403		coverage := flags.coverage
404		dump := flags.sAbiDump
405		rule := cc
406
407		switch srcFile.Ext() {
408		case ".s":
409			rule = ccNoDeps
410			fallthrough
411		case ".S":
412			ccCmd = "clang"
413			moduleCflags = asflags
414			tidy = false
415			coverage = false
416			dump = false
417		case ".c":
418			ccCmd = "clang"
419			moduleCflags = cflags
420			moduleToolingCflags = toolingCflags
421		case ".cpp", ".cc", ".mm":
422			ccCmd = "clang++"
423			moduleCflags = cppflags
424			moduleToolingCflags = toolingCppflags
425		default:
426			ctx.ModuleErrorf("File %s has unknown extension", srcFile)
427			continue
428		}
429
430		ccDesc := ccCmd
431
432		ccCmd = "${config.ClangBin}/" + ccCmd
433
434		var implicitOutputs android.WritablePaths
435		if coverage {
436			gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno")
437			implicitOutputs = append(implicitOutputs, gcnoFile)
438			coverageFiles = append(coverageFiles, gcnoFile)
439		}
440
441		ctx.Build(pctx, android.BuildParams{
442			Rule:            rule,
443			Description:     ccDesc + " " + srcFile.Rel(),
444			Output:          objFile,
445			ImplicitOutputs: implicitOutputs,
446			Input:           srcFile,
447			Implicits:       cFlagsDeps,
448			OrderOnly:       pathDeps,
449			Args: map[string]string{
450				"cFlags": moduleCflags,
451				"ccCmd":  ccCmd,
452			},
453		})
454
455		if tidy {
456			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
457			tidyFiles = append(tidyFiles, tidyFile)
458
459			ctx.Build(pctx, android.BuildParams{
460				Rule:        clangTidy,
461				Description: "clang-tidy " + srcFile.Rel(),
462				Output:      tidyFile,
463				Input:       srcFile,
464				// We must depend on objFile, since clang-tidy doesn't
465				// support exporting dependencies.
466				Implicit: objFile,
467				Args: map[string]string{
468					"cFlags":    moduleToolingCflags,
469					"tidyFlags": flags.tidyFlags,
470				},
471			})
472		}
473
474		if dump {
475			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
476			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
477
478			ctx.Build(pctx, android.BuildParams{
479				Rule:        sAbiDump,
480				Description: "header-abi-dumper " + srcFile.Rel(),
481				Output:      sAbiDumpFile,
482				Input:       srcFile,
483				Implicit:    objFile,
484				Args: map[string]string{
485					"cFlags":     moduleToolingCflags,
486					"exportDirs": flags.sAbiFlags,
487				},
488			})
489		}
490
491	}
492
493	return Objects{
494		objFiles:      objFiles,
495		tidyFiles:     tidyFiles,
496		coverageFiles: coverageFiles,
497		sAbiDumpFiles: sAbiDumpFiles,
498	}
499}
500
501// Generate a rule for compiling multiple .o files to a static library (.a)
502func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
503	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
504
505	if ctx.Darwin() {
506		transformDarwinObjToStaticLib(ctx, objFiles, flags, outputFile, deps)
507		return
508	}
509
510	arCmd := "${config.ClangBin}/llvm-ar"
511	arFlags := "crsD"
512	if !ctx.Darwin() {
513		arFlags += " -format=gnu"
514	}
515	if flags.arFlags != "" {
516		arFlags += " " + flags.arFlags
517	}
518
519	ctx.Build(pctx, android.BuildParams{
520		Rule:        ar,
521		Description: "static link " + outputFile.Base(),
522		Output:      outputFile,
523		Inputs:      objFiles,
524		Implicits:   deps,
525		Args: map[string]string{
526			"arFlags": arFlags,
527			"arCmd":   arCmd,
528		},
529	})
530}
531
532// Generate a rule for compiling multiple .o files to a static library (.a) on
533// darwin.  The darwin ar tool doesn't support @file for list files, and has a
534// very small command line length limit, so we have to split the ar into multiple
535// steps, each appending to the previous one.
536func transformDarwinObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
537	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
538
539	arFlags := "cqs"
540
541	if len(objFiles) == 0 {
542		dummy := android.PathForModuleOut(ctx, "dummy"+objectExtension)
543		dummyAr := android.PathForModuleOut(ctx, "dummy"+staticLibraryExtension)
544
545		ctx.Build(pctx, android.BuildParams{
546			Rule:        emptyFile,
547			Description: "empty object file",
548			Output:      dummy,
549			Implicits:   deps,
550		})
551
552		ctx.Build(pctx, android.BuildParams{
553			Rule:        darwinAr,
554			Description: "empty static archive",
555			Output:      dummyAr,
556			Input:       dummy,
557			Args: map[string]string{
558				"arFlags": arFlags,
559			},
560		})
561
562		ctx.Build(pctx, android.BuildParams{
563			Rule:        darwinAppendAr,
564			Description: "static link " + outputFile.Base(),
565			Output:      outputFile,
566			Input:       dummy,
567			Args: map[string]string{
568				"arFlags": "d",
569				"inAr":    dummyAr.String(),
570			},
571		})
572
573		return
574	}
575
576	// ARG_MAX on darwin is 262144, use half that to be safe
577	objFilesLists, err := splitListForSize(objFiles, 131072)
578	if err != nil {
579		ctx.ModuleErrorf("%s", err.Error())
580	}
581
582	var in, out android.WritablePath
583	for i, l := range objFilesLists {
584		in = out
585		out = outputFile
586		if i != len(objFilesLists)-1 {
587			out = android.PathForModuleOut(ctx, outputFile.Base()+strconv.Itoa(i))
588		}
589
590		build := android.BuildParams{
591			Rule:        darwinAr,
592			Description: "static link " + out.Base(),
593			Output:      out,
594			Inputs:      l,
595			Implicits:   deps,
596			Args: map[string]string{
597				"arFlags": arFlags,
598			},
599		}
600		if i != 0 {
601			build.Rule = darwinAppendAr
602			build.Args["inAr"] = in.String()
603		}
604		ctx.Build(pctx, build)
605	}
606}
607
608// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
609// and shared libraries, to a shared library (.so) or dynamic executable
610func TransformObjToDynamicBinary(ctx android.ModuleContext,
611	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
612	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
613
614	ldCmd := "${config.ClangBin}/clang++"
615
616	var libFlagsList []string
617
618	if len(flags.libFlags) > 0 {
619		libFlagsList = append(libFlagsList, flags.libFlags)
620	}
621
622	if len(wholeStaticLibs) > 0 {
623		if ctx.Host() && ctx.Darwin() {
624			libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
625		} else {
626			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
627			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
628			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
629		}
630	}
631
632	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
633		libFlagsList = append(libFlagsList, "-Wl,--start-group")
634	}
635	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
636	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
637		libFlagsList = append(libFlagsList, "-Wl,--end-group")
638	}
639
640	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
641		libFlagsList = append(libFlagsList, "-Wl,--start-group")
642	}
643	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
644	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
645		libFlagsList = append(libFlagsList, "-Wl,--end-group")
646	}
647
648	for _, lib := range sharedLibs {
649		libFlagsList = append(libFlagsList, lib.String())
650	}
651
652	deps = append(deps, staticLibs...)
653	deps = append(deps, lateStaticLibs...)
654	deps = append(deps, wholeStaticLibs...)
655	if crtBegin.Valid() {
656		deps = append(deps, crtBegin.Path(), crtEnd.Path())
657	}
658
659	ctx.Build(pctx, android.BuildParams{
660		Rule:        ld,
661		Description: "link " + outputFile.Base(),
662		Output:      outputFile,
663		Inputs:      objFiles,
664		Implicits:   deps,
665		Args: map[string]string{
666			"ldCmd":    ldCmd,
667			"crtBegin": crtBegin.String(),
668			"libFlags": strings.Join(libFlagsList, " "),
669			"ldFlags":  flags.ldFlags,
670			"crtEnd":   crtEnd.String(),
671		},
672	})
673}
674
675// Generate a rule to combine .dump sAbi dump files from multiple source files
676// into a single .ldump sAbi dump file
677func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
678	baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
679	excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath {
680
681	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
682	sabiLock.Lock()
683	lsdumpPaths = append(lsdumpPaths, outputFile.String())
684	sabiLock.Unlock()
685
686	implicits := android.Paths{soFile}
687	symbolFilterStr := "-so " + soFile.String()
688
689	if symbolFile.Valid() {
690		implicits = append(implicits, symbolFile.Path())
691		symbolFilterStr += " -v " + symbolFile.String()
692	}
693	for _, ver := range excludedSymbolVersions {
694		symbolFilterStr += " --exclude-symbol-version " + ver
695	}
696	for _, tag := range excludedSymbolTags {
697		symbolFilterStr += " --exclude-symbol-tag " + tag
698	}
699	ctx.Build(pctx, android.BuildParams{
700		Rule:        sAbiLink,
701		Description: "header-abi-linker " + outputFile.Base(),
702		Output:      outputFile,
703		Inputs:      sAbiDumps,
704		Implicits:   implicits,
705		Args: map[string]string{
706			"symbolFilter":        symbolFilterStr,
707			"arch":                ctx.Arch().ArchType.Name,
708			"exportedHeaderFlags": exportedHeaderFlags,
709		},
710	})
711	return android.OptionalPathForPath(outputFile)
712}
713
714func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
715	outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
716	ctx.Build(pctx, android.BuildParams{
717		Rule:        unzipRefSAbiDump,
718		Description: "gunzip" + outputFile.Base(),
719		Output:      outputFile,
720		Input:       zippedRefDump,
721	})
722	return outputFile
723}
724
725func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
726	baseName, exportedHeaderFlags string, isLlndk, isVndkExt bool) android.OptionalPath {
727
728	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
729	libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
730	createReferenceDumpFlags := ""
731
732	localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
733	if exportedHeaderFlags == "" {
734		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
735	}
736	if isLlndk {
737		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-consider-opaque-types-different")
738		createReferenceDumpFlags = "--llndk"
739	}
740	if isVndkExt {
741		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
742	}
743
744	ctx.Build(pctx, android.BuildParams{
745		Rule:        sAbiDiff,
746		Description: "header-abi-diff " + outputFile.Base(),
747		Output:      outputFile,
748		Input:       inputDump,
749		Implicit:    referenceDump,
750		Args: map[string]string{
751			"referenceDump":            referenceDump.String(),
752			"libName":                  libName,
753			"arch":                     ctx.Arch().ArchType.Name,
754			"allowFlags":               strings.Join(localAbiCheckAllowFlags, " "),
755			"createReferenceDumpFlags": createReferenceDumpFlags,
756		},
757	})
758	return android.OptionalPathForPath(outputFile)
759}
760
761// Generate a rule for extracting a table of contents from a shared library (.so)
762func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
763	outputFile android.WritablePath, flags builderFlags) {
764
765	var format string
766	var crossCompile string
767	if ctx.Darwin() {
768		format = "--macho"
769		crossCompile = "${config.MacToolPath}"
770	} else if ctx.Windows() {
771		format = "--pe"
772		crossCompile = gccCmd(flags.toolchain, "")
773	} else {
774		format = "--elf"
775		crossCompile = gccCmd(flags.toolchain, "")
776	}
777
778	ctx.Build(pctx, android.BuildParams{
779		Rule:        toc,
780		Description: "generate toc " + inputFile.Base(),
781		Output:      outputFile,
782		Input:       inputFile,
783		Args: map[string]string{
784			"crossCompile": crossCompile,
785			"format":       format,
786		},
787	})
788}
789
790// Generate a rule for compiling multiple .o files to a .o using ld partial linking
791func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
792	flags builderFlags, outputFile android.WritablePath) {
793
794	ldCmd := "${config.ClangBin}/clang++"
795
796	ctx.Build(pctx, android.BuildParams{
797		Rule:        partialLd,
798		Description: "link " + outputFile.Base(),
799		Output:      outputFile,
800		Inputs:      objFiles,
801		Args: map[string]string{
802			"ldCmd":   ldCmd,
803			"ldFlags": flags.ldFlags,
804		},
805	})
806}
807
808// Generate a rule for runing objcopy --prefix-symbols on a binary
809func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
810	flags builderFlags, outputFile android.WritablePath) {
811
812	objcopyCmd := gccCmd(flags.toolchain, "objcopy")
813
814	ctx.Build(pctx, android.BuildParams{
815		Rule:        prefixSymbols,
816		Description: "prefix symbols " + outputFile.Base(),
817		Output:      outputFile,
818		Input:       inputFile,
819		Args: map[string]string{
820			"objcopyCmd": objcopyCmd,
821			"prefix":     prefix,
822		},
823	})
824}
825
826func TransformStrip(ctx android.ModuleContext, inputFile android.Path,
827	outputFile android.WritablePath, flags builderFlags) {
828
829	crossCompile := gccCmd(flags.toolchain, "")
830	args := ""
831	if flags.stripAddGnuDebuglink {
832		args += " --add-gnu-debuglink"
833	}
834	if flags.stripKeepMiniDebugInfo {
835		args += " --keep-mini-debug-info"
836	}
837	if flags.stripKeepSymbols {
838		args += " --keep-symbols"
839	}
840	if flags.stripKeepSymbolsList != "" {
841		args += " -k" + flags.stripKeepSymbolsList
842	}
843	if flags.stripUseGnuStrip {
844		args += " --use-gnu-strip"
845	}
846
847	ctx.Build(pctx, android.BuildParams{
848		Rule:        strip,
849		Description: "strip " + outputFile.Base(),
850		Output:      outputFile,
851		Input:       inputFile,
852		Args: map[string]string{
853			"crossCompile": crossCompile,
854			"args":         args,
855		},
856	})
857}
858
859func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
860	outputFile android.WritablePath) {
861
862	ctx.Build(pctx, android.BuildParams{
863		Rule:        darwinStrip,
864		Description: "strip " + outputFile.Base(),
865		Output:      outputFile,
866		Input:       inputFile,
867	})
868}
869
870func TransformCoverageFilesToLib(ctx android.ModuleContext,
871	inputs Objects, flags builderFlags, baseName string) android.OptionalPath {
872
873	if len(inputs.coverageFiles) > 0 {
874		outputFile := android.PathForModuleOut(ctx, baseName+".gcnodir")
875
876		TransformObjToStaticLib(ctx, inputs.coverageFiles, flags, outputFile, nil)
877
878		return android.OptionalPathForPath(outputFile)
879	}
880
881	return android.OptionalPath{}
882}
883
884func gccCmd(toolchain config.Toolchain, cmd string) string {
885	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
886}
887
888func splitListForSize(list android.Paths, limit int) (lists []android.Paths, err error) {
889	var i int
890
891	start := 0
892	bytes := 0
893	for i = range list {
894		l := len(list[i].String())
895		if l > limit {
896			return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
897		}
898		if bytes+l > limit {
899			lists = append(lists, list[start:i])
900			start = i
901			bytes = 0
902		}
903		bytes += l + 1 // count a space between each list element
904	}
905
906	lists = append(lists, list[start:])
907
908	totalLen := 0
909	for _, l := range lists {
910		totalLen += len(l)
911	}
912	if totalLen != len(list) {
913		panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
914	}
915	return lists, nil
916}
917