| package bootstrap |
| |
| import ( |
| "fmt" |
| "maps" |
| "path/filepath" |
| "reflect" |
| |
| "github.com/google/blueprint" |
| "github.com/google/blueprint/bootstrap/bpdoc" |
| "github.com/google/blueprint/pathtools" |
| ) |
| |
| // ModuleTypeDocs returns a list of bpdoc.ModuleType objects that contain information relevant |
| // to generating documentation for module types supported by the primary builder. |
| func ModuleTypeDocs(ctx *blueprint.Context, factories map[string]reflect.Value) ([]*bpdoc.Package, error) { |
| // Find the module that's marked as the "primary builder", which means it's |
| // creating the binary that we'll use to generate the non-bootstrap |
| // build.ninja file. |
| var primaryBuilders []blueprint.Module |
| ctx.VisitAllModules(func(module blueprint.Module) { |
| if ctx.PrimaryModule(module) == module { |
| if _, ok := blueprint.SingletonModuleProvider(ctx, module, PrimaryBuilderProvider); ok { |
| primaryBuilders = append(primaryBuilders, module) |
| } |
| } |
| }) |
| |
| var primaryBuilder blueprint.Module |
| switch len(primaryBuilders) { |
| case 0: |
| return nil, fmt.Errorf("no primary builder module present") |
| |
| case 1: |
| primaryBuilder = primaryBuilders[0] |
| |
| default: |
| return nil, fmt.Errorf("multiple primary builder modules present") |
| } |
| |
| pkgFiles := make(map[string][]string) |
| ctx.VisitDepsDepthFirst(primaryBuilder, func(module blueprint.Module) { |
| if info, ok := blueprint.SingletonModuleProvider(ctx, module, DocsPackageProvider); ok { |
| pkgFiles[info.PkgPath] = pathtools.PrefixPaths(info.Srcs, |
| filepath.Join(ctx.SrcDir(), ctx.ModuleDir(module))) |
| } |
| }) |
| |
| mergedFactories := maps.Clone(factories) |
| |
| for moduleType, factory := range ctx.ModuleTypeFactories() { |
| if _, exists := mergedFactories[moduleType]; !exists { |
| mergedFactories[moduleType] = reflect.ValueOf(factory) |
| } |
| } |
| |
| return bpdoc.AllPackages(pkgFiles, mergedFactories, ctx.ModuleTypePropertyStructs()) |
| } |