Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/cc/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 8 kB image not shown  

Quelle  ccdeps.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cc

import (
 "encoding/json"
 "fmt"
 "path"
 "sort"
 "strings"

 "android/soong/android"
)

// This singleton collects cc modules' source and flags into to a json file.
// It does so for generating CMakeLists.txt project files needed data when
// either make, mm, mma, mmm or mmma is called.
// The info file is generated in $OUT/module_bp_cc_depend.json.

func init() {
 android.RegisterParallelSingletonType("ccdeps_generator", ccDepsGeneratorSingleton)
}

func ccDepsGeneratorSingleton() android.Singleton {
 return &ccdepsGeneratorSingleton{}
}

type ccdepsGeneratorSingleton struct {
 outputPath android.Path
}

const (
 ccdepsJsonFileName = "module_bp_cc_deps.json"
 cClang             = "clang"
 cppClang           = "clang++"
)

type ccIdeInfo struct {
 Path                 []string     `json:"path,omitempty"`
 Srcs                 []string     `json:"srcs,omitempty"`
 Global_Common_Flags  ccParameters `json:"global_common_flags,omitempty"`
 Local_Common_Flags   ccParameters `json:"local_common_flags,omitempty"`
 Global_C_flags       ccParameters `json:"global_c_flags,omitempty"`
 Local_C_flags        ccParameters `json:"local_c_flags,omitempty"`
 Global_C_only_flags  ccParameters `json:"global_c_only_flags,omitempty"`
 Local_C_only_flags   ccParameters `json:"local_c_only_flags,omitempty"`
 Global_Cpp_flags     ccParameters `json:"global_cpp_flags,omitempty"`
 Local_Cpp_flags      ccParameters `json:"local_cpp_flags,omitempty"`
 System_include_flags ccParameters `json:"system_include_flags,omitempty"`
 Module_name          string       `json:"module_name,omitempty"`
}

type ccParameters struct {
 HeaderSearchPath       []string          `json:"header_search_path,omitempty"`
 SystemHeaderSearchPath []string          `json:"system_search_path,omitempty"`
 FlagParameters         []string          `json:"flag,omitempty"`
 SysRoot                string            `json:"system_root,omitempty"`
 RelativeFilePathFlags  map[string]string `json:"relative_file_path,omitempty"`
}

type ccMapIdeInfos map[string]ccIdeInfo

type ccDeps struct {
 C_clang   string        `json:"clang,omitempty"`
 Cpp_clang string        `json:"clang++,omitempty"`
 Modules   ccMapIdeInfos `json:"modules,omitempty"`
}

func (c *ccdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 // (b/204397180) Generate module_bp_cc_deps.json by default.
 moduleDeps := ccDeps{}
 moduleInfos := map[string]ccIdeInfo{}

 // Track if best variant (device arch match) has been found.
 bestVariantFound := map[string]bool{}

 pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
 moduleDeps.C_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cClang)
 moduleDeps.Cpp_clang = fmt.Sprintf("%s%s", buildCMakePath(pathToCC), cppClang)

 ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
  if ccModule, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
   if ccModule.CompilerInfo != nil {
    generateCLionProjectData(ctx, module, ccModule, bestVariantFound, moduleInfos)
   }
  }
 })

 moduleDeps.Modules = moduleInfos

 ccfpath := android.PathForOutput(ctx, ccdepsJsonFileName)
 err := createJsonFile(moduleDeps, ccfpath)
 if err != nil {
  ctx.Errorf(err.Error())
 }
 c.outputPath = ccfpath

 // This is necessary to satisfy the dangling rules check as this file is written by Soong rather than a rule.
 ctx.Build(pctx, android.BuildParams{
  Rule:   android.TouchRule,
  Output: ccfpath,
 })
 ctx.DistForGoals([]string{"general-tests", "module-info"}, c.outputPath)
}

func parseCompilerCCParameters(ctx android.SingletonContext, params []string) ccParameters {
 compilerParams := ccParameters{}

 cparams := []string{}
 for _, param := range params {
  param, _ = evalVariable(ctx, param)
  cparams = append(cparams, param)
 }

 // Soong does not guarantee that each flag will be in an individual string. e.g: The
 // input received could be:
 // params = {"-isystem", "path/to/system"}
 // or it could be
 // params = {"-isystem path/to/system"}
 // To normalize the input, we split all strings with the "space" character and consolidate
 // all tokens into a flattened parameters list
 cparams = normalizeParameters(cparams)

 for i := 0; i < len(cparams); i++ {
  param := cparams[i]
  if param == "" {
   continue
  }

  switch categorizeParameter(param) {
  case headerSearchPath:
   compilerParams.HeaderSearchPath =
    append(compilerParams.HeaderSearchPath, strings.TrimPrefix(param, "-I"))
  case systemHeaderSearchPath:
   if i < len(cparams)-1 {
    compilerParams.SystemHeaderSearchPath = append(compilerParams.SystemHeaderSearchPath, cparams[i+1])
   }
   i = i + 1
  case flag:
   c := cleanupParameter(param)
   compilerParams.FlagParameters = append(compilerParams.FlagParameters, c)
  case systemRoot:
   if i < len(cparams)-1 {
    compilerParams.SysRoot = cparams[i+1]
   }
   i = i + 1
  case relativeFilePathFlag:
   flagComponents := strings.Split(param, "=")
   if len(flagComponents) == 2 {
    if compilerParams.RelativeFilePathFlags == nil {
     compilerParams.RelativeFilePathFlags = map[string]string{}
    }
    compilerParams.RelativeFilePathFlags[flagComponents[0]] = flagComponents[1]
   }
  }
 }
 return compilerParams
}

func generateCLionProjectData(ctx android.SingletonContext, module android.ModuleProxy,
 ccModule *CcInfo, bestVariantFound map[string]bool, moduleInfos map[string]ccIdeInfo) {
 commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
 moduleName := commonInfo.BaseModuleName
 srcs := ccModule.CompilerInfo.Srcs
 target := commonInfo.Target
 // Skip if best variant has already been found.
 if bestVariantFound[moduleName] {
  return
 }

 // Skip if sources are empty.
 if len(srcs) == 0 {
  return
 }

 // Check if device arch matches, in which case this is the best variant and takes precedence.
 if target.Os.Class == android.Device && target.Arch.ArchType.Name == ctx.DeviceConfig().DeviceArch() {
  bestVariantFound[moduleName] = true
 } else if _, ok := moduleInfos[moduleName]; ok {
  // Skip because this isn't the best variant and a previous one has already been added.
  // Heuristically, ones that appear first are likely to be more relevant.
  return
 }

 dpInfo := ccIdeInfo{}

 dpInfo.Path = append(dpInfo.Path, path.Dir(ctx.BlueprintFile(module)))
 dpInfo.Srcs = append(dpInfo.Srcs, srcs.Strings()...)
 dpInfo.Path = android.FirstUniqueStrings(dpInfo.Path)
 dpInfo.Srcs = android.FirstUniqueStrings(dpInfo.Srcs)

 dpInfo.Global_Common_Flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CommonFlags)
 dpInfo.Local_Common_Flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CommonFlags)
 dpInfo.Global_C_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CFlags)
 dpInfo.Local_C_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CFlags)
 dpInfo.Global_C_only_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.ConlyFlags)
 dpInfo.Local_C_only_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.ConlyFlags)
 dpInfo.Global_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.GlobalFlags.CppFlags)
 dpInfo.Local_Cpp_flags = parseCompilerCCParameters(ctx, ccModule.LocalFlags.CppFlags)
 dpInfo.System_include_flags = parseCompilerCCParameters(ctx, ccModule.SystemIncludeFlags)

 dpInfo.Module_name = moduleName

 moduleInfos[moduleName] = dpInfo
}

type Deal struct {
 Name    string
 ideInfo ccIdeInfo
}

type Deals []Deal

// Ensure it satisfies sort.Interface
func (d Deals) Len() int           { return len(d) }
func (d Deals) Less(i, j int) bool { return d[i].Name < d[j].Name }
func (d Deals) Swap(i, j int)      { d[i], d[j] = d[j], d[i] }

func sortMap(moduleInfos map[string]ccIdeInfo) map[string]ccIdeInfo {
 var deals Deals
 for k, v := range moduleInfos {
  deals = append(deals, Deal{k, v})
 }

 sort.Sort(deals)

 m := map[string]ccIdeInfo{}
 for _, d := range deals {
  m[d.Name] = d.ideInfo
 }
 return m
}

func createJsonFile(moduleDeps ccDeps, ccfpath android.WritablePath) error {
 buf, err := json.MarshalIndent(moduleDeps, "", "\t")
 if err != nil {
  return fmt.Errorf("JSON marshal of cc deps failed: %s", err)
 }
 err = android.WriteFileToOutputDir(ccfpath, buf, 0666)
 if err != nil {
  return fmt.Errorf("Writing cc deps to %s failed: %s", ccfpath.String(), err)
 }
 return nil
}

[Dauer der Verarbeitung: 0.1 Sekunden, vorverarbeitet 2026-06-28]