Creation of C Flags Build Variables
Modifications made to soong/cc to look for specific C Flags used by Android modules and store name of module into a build variable array. Bug: 140442588 Test: Executed m dist and presubmit Change-Id: If46a11462369c43bbcd445156aff0641514c58b1
This commit is contained in:
@@ -172,6 +172,7 @@ bootstrap_go_package {
|
||||
"cc/vndk_prebuilt.go",
|
||||
"cc/xom.go",
|
||||
|
||||
"cc/cflag_artifacts.go",
|
||||
"cc/cmakelists.go",
|
||||
"cc/compdb.go",
|
||||
"cc/compiler.go",
|
||||
|
188
cc/cflag_artifacts.go
Normal file
188
cc/cflag_artifacts.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package cc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
func init() {
|
||||
android.RegisterSingletonType("cflag_artifacts_text", cflagArtifactsTextFactory)
|
||||
}
|
||||
|
||||
var (
|
||||
TrackedCFlags = []string{
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
"-Wthread-safety",
|
||||
"-O3",
|
||||
}
|
||||
|
||||
TrackedCFlagsDir = []string{
|
||||
"device/google/",
|
||||
"vendor/google/",
|
||||
}
|
||||
)
|
||||
|
||||
const FileBP = 50
|
||||
|
||||
// Stores output files.
|
||||
type cflagArtifactsText struct {
|
||||
interOutputs map[string]android.WritablePaths
|
||||
outputs android.WritablePaths
|
||||
}
|
||||
|
||||
// allowedDir verifies if the directory/project is part of the TrackedCFlagsDir
|
||||
// filter.
|
||||
func allowedDir(subdir string) bool {
|
||||
subdir += "/"
|
||||
for _, prefix := range TrackedCFlagsDir {
|
||||
if strings.HasPrefix(subdir, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *cflagArtifactsText) genFlagFilename(flag string) string {
|
||||
return fmt.Sprintf("module_cflags%s.txt", flag)
|
||||
}
|
||||
|
||||
// incrementFile is used to generate an output path object with the passed in flag
|
||||
// and part number.
|
||||
// e.g. FLAG + part # -> out/soong/cflags/module_cflags-FLAG.txt.0
|
||||
func (s *cflagArtifactsText) incrementFile(ctx android.SingletonContext,
|
||||
flag string, part int) (string, android.OutputPath) {
|
||||
|
||||
filename := fmt.Sprintf("%s.%d", s.genFlagFilename(flag), part)
|
||||
filepath := android.PathForOutput(ctx, "cflags", filename)
|
||||
s.interOutputs[flag] = append(s.interOutputs[flag], filepath)
|
||||
return filename, filepath
|
||||
}
|
||||
|
||||
// GenCFlagArtifactParts is used to generate the build rules which produce the
|
||||
// intermediary files for each desired C Flag artifact
|
||||
// e.g. module_cflags-FLAG.txt.0, module_cflags-FLAG.txt.1, ...
|
||||
func (s *cflagArtifactsText) GenCFlagArtifactParts(ctx android.SingletonContext,
|
||||
flag string, using bool, modules []string, part int) int {
|
||||
|
||||
cleanedName := strings.Replace(flag, "=", "_", -1)
|
||||
filename, filepath := s.incrementFile(ctx, cleanedName, part)
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.Command().Textf("rm -f %s", filepath.String())
|
||||
|
||||
if using {
|
||||
rule.Command().
|
||||
Textf("echo '# Modules using %s'", flag).
|
||||
FlagWithOutput(">> ", filepath)
|
||||
} else {
|
||||
rule.Command().
|
||||
Textf("echo '# Modules not using %s'", flag).
|
||||
FlagWithOutput(">> ", filepath)
|
||||
}
|
||||
|
||||
length := len(modules)
|
||||
|
||||
if length == 0 {
|
||||
rule.Build(pctx, ctx, filename, "gen "+filename)
|
||||
part++
|
||||
}
|
||||
|
||||
// Following loop splits the module list for each tracked C Flag into
|
||||
// chunks of length FileBP (file breakpoint) and generates a partial artifact
|
||||
// (intermediary file) build rule for each split.
|
||||
moduleShards := android.ShardStrings(modules, FileBP)
|
||||
for index, shard := range moduleShards {
|
||||
rule.Command().
|
||||
Textf("for m in %s; do echo $m",
|
||||
strings.Join(proptools.ShellEscapeList(shard), " ")).
|
||||
FlagWithOutput(">> ", filepath).
|
||||
Text("; done")
|
||||
rule.Build(pctx, ctx, filename, "gen "+filename)
|
||||
|
||||
if index+1 != len(moduleShards) {
|
||||
filename, filepath = s.incrementFile(ctx, cleanedName, part+index+1)
|
||||
rule = android.NewRuleBuilder()
|
||||
rule.Command().Textf("rm -f %s", filepath.String())
|
||||
}
|
||||
}
|
||||
|
||||
return part + len(moduleShards)
|
||||
}
|
||||
|
||||
// GenCFlagArtifacts is used to generate build rules which combine the
|
||||
// intermediary files of a specific tracked flag into a single C Flag artifact
|
||||
// for each tracked flag.
|
||||
// e.g. module_cflags-FLAG.txt.0 + module_cflags-FLAG.txt.1 = module_cflags-FLAG.txt
|
||||
func (s *cflagArtifactsText) GenCFlagArtifacts(ctx android.SingletonContext) {
|
||||
// Scans through s.interOutputs and creates a build rule for each tracked C
|
||||
// Flag that concatenates the associated intermediary file into a single
|
||||
// artifact.
|
||||
for _, flag := range TrackedCFlags {
|
||||
// Generate build rule to combine related intermediary files into a
|
||||
// C Flag artifact
|
||||
rule := android.NewRuleBuilder()
|
||||
filename := s.genFlagFilename(flag)
|
||||
outputpath := android.PathForOutput(ctx, "cflags", filename)
|
||||
rule.Command().
|
||||
Text("cat").
|
||||
Inputs(s.interOutputs[flag].Paths()).
|
||||
FlagWithOutput("> ", outputpath)
|
||||
rule.Build(pctx, ctx, filename, "gen "+filename)
|
||||
s.outputs = append(s.outputs, outputpath)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *cflagArtifactsText) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
modulesWithCFlag := make(map[string][]string)
|
||||
|
||||
// Scan through all modules, selecting the ones that are part of the filter,
|
||||
// and then storing into a map which tracks whether or not tracked C flag is
|
||||
// used or not.
|
||||
ctx.VisitAllModules(func(module android.Module) {
|
||||
if ccModule, ok := module.(*Module); ok {
|
||||
if allowedDir(ctx.ModuleDir(ccModule)) {
|
||||
cflags := ccModule.flags.CFlags
|
||||
cppflags := ccModule.flags.CppFlags
|
||||
module := fmt.Sprintf("%s:%s (%s)",
|
||||
ctx.BlueprintFile(ccModule),
|
||||
ctx.ModuleName(ccModule),
|
||||
ctx.ModuleSubDir(ccModule))
|
||||
for _, flag := range TrackedCFlags {
|
||||
if inList(flag, cflags) || inList(flag, cppflags) {
|
||||
modulesWithCFlag[flag] = append(modulesWithCFlag[flag], module)
|
||||
} else {
|
||||
modulesWithCFlag["!"+flag] = append(modulesWithCFlag["!"+flag], module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Traversing map and setting up rules to produce intermediary files which
|
||||
// contain parts of each expected C Flag artifact.
|
||||
for _, flag := range TrackedCFlags {
|
||||
sort.Strings(modulesWithCFlag[flag])
|
||||
part := s.GenCFlagArtifactParts(ctx, flag, true, modulesWithCFlag[flag], 0)
|
||||
sort.Strings(modulesWithCFlag["!"+flag])
|
||||
s.GenCFlagArtifactParts(ctx, flag, false, modulesWithCFlag["!"+flag], part)
|
||||
}
|
||||
|
||||
// Combine intermediary files into a single C Flag artifact.
|
||||
s.GenCFlagArtifacts(ctx)
|
||||
}
|
||||
|
||||
func cflagArtifactsTextFactory() android.Singleton {
|
||||
return &cflagArtifactsText{
|
||||
interOutputs: make(map[string]android.WritablePaths),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *cflagArtifactsText) MakeVars(ctx android.MakeVarsContext) {
|
||||
ctx.Strict("SOONG_MODULES_CFLAG_ARTIFACTS", strings.Join(s.outputs.Strings(), " "))
|
||||
}
|
Reference in New Issue
Block a user