@@ -45,16 +45,20 @@ import (
4545)
4646
4747const (
48- languageName = "starlarkrepository"
49- repoNameDirectiveName = languageName + "_repo_name"
50- rootDirectiveName = languageName + "_root"
51- excludeDirectiveName = languageName + "_exclude"
52- logFileDirectiveName = languageName + "_log_file"
53- starlarkModuleKind = "starlark_module"
54- starlarkModuleLibraryKind = "starlark_module_library"
55- starlarkModuleLibraryName = "modules"
56- fileType = ".bzl"
57- visibilityPublic = "//visibility:public"
48+ languageName = "starlarkrepository"
49+ repoNameDirectiveName = languageName + "_repo_name"
50+ rootDirectiveName = languageName + "_root"
51+ excludeDirectiveName = languageName + "_exclude"
52+ logFileDirectiveName = languageName + "_log_file"
53+ starlarkModuleKind = "starlark_module"
54+ starlarkModuleLibraryKind = "starlark_module_library"
55+ starlarkModuleLibraryName = "modules"
56+ starlarkPackageKind = "starlark_package"
57+ starlarkPackageLibraryKind = "starlark_package_library"
58+ starlarkPackageLibraryName = "starlark_packages"
59+ bzlFileType = ".bzl"
60+ packageFileType = ".package"
61+ visibilityPublic = "//visibility:public"
5862)
5963
6064var (
7377 NonEmptyAttrs : map [string ]bool {"src" : true },
7478 },
7579 }
80+ starlarkPackageLibraryKindInfo = map [string ]rule.KindInfo {
81+ starlarkPackageLibraryKind : {
82+ NonEmptyAttrs : map [string ]bool {"packages" : true },
83+ ResolveAttrs : map [string ]bool {"packages" : true },
84+ },
85+ }
86+ starlarkPackageKindInfo = map [string ]rule.KindInfo {
87+ starlarkPackageKind : {
88+ NonEmptyAttrs : map [string ]bool {"src" : true },
89+ },
90+ }
7691 starlarkModuleLibraryLoadInfo = rule.LoadInfo {
7792 Name : "@build_stack_rules_proto//rules:starlark_module_library.bzl" ,
7893 Symbols : []string {starlarkModuleLibraryKind },
8196 Name : "@build_stack_rules_proto//rules:starlark_module.bzl" ,
8297 Symbols : []string {starlarkModuleKind },
8398 }
99+ starlarkPackageLibraryLoadInfo = rule.LoadInfo {
100+ Name : "@build_stack_rules_proto//rules:starlark_package_library.bzl" ,
101+ Symbols : []string {starlarkPackageLibraryKind },
102+ }
103+ starlarkPackageLoadInfo = rule.LoadInfo {
104+ Name : "@build_stack_rules_proto//rules:starlark_package.bzl" ,
105+ Symbols : []string {starlarkPackageKind },
106+ }
84107)
85108
86109type starlarkRepositoryLang struct {
@@ -201,6 +224,8 @@ func (*starlarkRepositoryLang) Kinds() map[string]rule.KindInfo {
201224 kinds := map [string ]rule.KindInfo {}
202225 maps .Copy (kinds , starlarkModuleLibraryKindInfo )
203226 maps .Copy (kinds , starlarkModuleKindInfo )
227+ maps .Copy (kinds , starlarkPackageLibraryKindInfo )
228+ maps .Copy (kinds , starlarkPackageKindInfo )
204229 return kinds
205230}
206231
@@ -211,6 +236,8 @@ func (*starlarkRepositoryLang) Loads() []rule.LoadInfo {
211236 return []rule.LoadInfo {
212237 starlarkModuleLibraryLoadInfo ,
213238 starlarkModuleLoadInfo ,
239+ starlarkPackageLibraryLoadInfo ,
240+ starlarkPackageLoadInfo ,
214241 }
215242}
216243
@@ -229,6 +256,8 @@ func (ext *starlarkRepositoryLang) Imports(c *config.Config, r *rule.Rule, f *ru
229256 switch r .Kind () {
230257 case starlarkModuleKind :
231258 return ext .starlarkModuleImports (c , r , f )
259+ case starlarkPackageKind :
260+ return ext .starlarkPackageImports (c , r , f )
232261 default :
233262 return nil
234263 }
@@ -242,6 +271,13 @@ func (ext *starlarkRepositoryLang) starlarkModuleImports(_ *config.Config, r *ru
242271 }
243272}
244273
274+ func (ext * starlarkRepositoryLang ) starlarkPackageImports (_ * config.Config , r * rule.Rule , f * rule.File ) []resolve.ImportSpec {
275+ return []resolve.ImportSpec {
276+ {Lang : languageName , Imp : fmt .Sprintf ("//%s:%s" , f .Pkg , r .AttrString ("src" ))},
277+ {Lang : languageName , Imp : starlarkPackageKind },
278+ }
279+ }
280+
245281// Embeds returns a list of labels of rules that the given rule embeds. If a
246282// rule is embedded by another importable rule of the same language, only the
247283// embedding rule will be indexed. The embedding rule will inherit the imports
@@ -261,6 +297,8 @@ func (ext *starlarkRepositoryLang) Resolve(c *config.Config, ix *resolve.RuleInd
261297 switch r .Kind () {
262298 case starlarkModuleLibraryKind :
263299 ext .starlarkModuleLibraryResolve (c , ix , rc , r , importsRaw , from )
300+ case starlarkPackageLibraryKind :
301+ ext .starlarkPackageLibraryResolve (c , ix , rc , r , importsRaw , from )
264302 }
265303}
266304
@@ -309,10 +347,24 @@ func (ext *starlarkRepositoryLang) GenerateRules(args language.GenerateArgs) (re
309347 log .Printf ("generated %s %s/%s" , r .Kind (), args .Rel , r .Name ())
310348 }
311349
350+ for _ , f := range args .RegularFiles {
351+ if ! isBuildPackageFile (f ) {
352+ continue
353+ }
354+ r , imports := ext .starlarkPackageRule (args , f )
355+ result .Gen = append (result .Gen , r )
356+ result .Imports = append (result .Imports , imports )
357+ log .Printf ("generated %s %s/%s" , r .Kind (), args .Rel , r .Name ())
358+ }
359+
312360 if _ , ok := getMatchingRoot (args .Rel , ext .roots ); ok {
313361 r , imports := ext .starlarkModuleLibraryRule (args )
314362 result .Gen = append (result .Gen , r )
315363 result .Imports = append (result .Imports , imports )
364+
365+ r , imports = ext .starlarkPackageLibraryRule (args )
366+ result .Gen = append (result .Gen , r )
367+ result .Imports = append (result .Imports , imports )
316368 }
317369
318370 return
@@ -344,7 +396,7 @@ func mustListFiles(logf LogFunc, dir string) []string {
344396}
345397func (ext * starlarkRepositoryLang ) starlarkModuleRule (args language.GenerateArgs , src string , loadStmts []* build.LoadStmt ) (* rule.Rule , []any ) {
346398
347- name := strings .TrimSuffix (src , fileType )
399+ name := strings .TrimSuffix (src , bzlFileType )
348400 ext .logf ("generating %s rule for %s //%s:%s" , starlarkModuleKind , src , args .Rel , name )
349401
350402 loads := make ([]string , 0 , len (loadStmts ))
@@ -376,6 +428,59 @@ func (ext *starlarkRepositoryLang) starlarkModuleLibraryRule(_ language.Generate
376428 return r , []any {}
377429}
378430
431+ func (ext * starlarkRepositoryLang ) starlarkPackageRule (args language.GenerateArgs , src string ) (* rule.Rule , []any ) {
432+ // Sanitize the filename into a target name: "BUILD.package" -> "BUILD_package",
433+ // "BUILD.bazel.package" -> "BUILD_bazel_package". This avoids clashing with
434+ // `pkg.bzl`-derived `starlark_module(name = "pkg")` targets that exist in many
435+ // Starlark codebases.
436+ name := strings .ReplaceAll (src , "." , "_" )
437+ ext .logf ("generating %s rule for %s //%s:%s" , starlarkPackageKind , src , args .Rel , name )
438+
439+ r := rule .NewRule (starlarkPackageKind , name )
440+ r .SetAttr ("src" , src )
441+ r .SetAttr ("visibility" , []string {visibilityPublic })
442+
443+ return r , []any {}
444+ }
445+
446+ func (ext * starlarkRepositoryLang ) starlarkPackageLibraryRule (_ language.GenerateArgs ) (* rule.Rule , []any ) {
447+ r := rule .NewRule (starlarkPackageLibraryKind , starlarkPackageLibraryName )
448+ if ext .bazelVersion != "" {
449+ r .SetAttr ("bazelversion" , ext .bazelVersion )
450+ }
451+ if len (ext .bazelIgnore ) > 0 {
452+ r .SetAttr ("bazelignore" , ext .bazelIgnore )
453+ }
454+ r .SetAttr ("visibility" , []string {visibilityPublic })
455+ return r , []any {}
456+ }
457+
458+ func (ext * starlarkRepositoryLang ) starlarkPackageLibraryResolve (c * config.Config , ix * resolve.RuleIndex , _ * repo.RemoteCache , r * rule.Rule , _ interface {}, from label.Label ) {
459+ root , isRoot := getMatchingRoot (from .Pkg , ext .roots )
460+ if ! isRoot {
461+ ext .logf ("skipping packages resolution for %v (not a root: %v)" , from , ext .roots )
462+ return
463+ }
464+
465+ var packages []string
466+
467+ matches := ix .FindRulesByImportWithConfig (c , resolve.ImportSpec {
468+ Lang : languageName ,
469+ Imp : starlarkPackageKind ,
470+ }, languageName )
471+ for _ , m := range matches {
472+ depLabel := m .Label .Rel (from .Repo , from .Pkg )
473+ if strings .HasPrefix (depLabel .Pkg , root ) {
474+ packages = append (packages , depLabel .String ())
475+ }
476+ }
477+
478+ if len (packages ) > 0 {
479+ sort .Strings (packages )
480+ r .SetAttr ("packages" , packages )
481+ }
482+ }
483+
379484func (ext * starlarkRepositoryLang ) starlarkModuleLibraryResolve (c * config.Config , ix * resolve.RuleIndex , _ * repo.RemoteCache , r * rule.Rule , _ interface {}, from label.Label ) {
380485 // only perform resolve if this is one of the roots
381486 root , isRoot := getMatchingRoot (from .Pkg , ext .roots )
@@ -511,7 +616,11 @@ func readFileLines(filePath string, logf LogFunc) ([]string, error) {
511616}
512617
513618func isBzlSourceFile (f string ) bool {
514- return strings .HasSuffix (f , fileType ) && ! ignoreSuffix .Matches (f )
619+ return strings .HasSuffix (f , bzlFileType ) && ! ignoreSuffix .Matches (f )
620+ }
621+
622+ func isBuildPackageFile (f string ) bool {
623+ return f == "BUILD.package" || f == "BUILD.bazel.package"
515624}
516625
517626func getBzlFileLoadsStmts (path , rel string , logf LogFunc ) (* build.File , []* build.LoadStmt , error ) {
0 commit comments