diff --git a/rust/prebuilt.go b/rust/prebuilt.go index 6f17272f7..6cdd07de9 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -22,6 +22,7 @@ func init() { android.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory) android.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory) android.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory) + android.RegisterModuleType("rust_prebuilt_proc_macro", PrebuiltProcMacroFactory) } type PrebuiltProperties struct { @@ -38,8 +39,42 @@ type prebuiltLibraryDecorator struct { Properties PrebuiltProperties } +type prebuiltProcMacroDecorator struct { + android.Prebuilt + + *procMacroDecorator + Properties PrebuiltProperties +} + +func PrebuiltProcMacroFactory() android.Module { + module, _ := NewPrebuiltProcMacro(android.HostSupportedNoCross) + return module.Init() +} + +type rustPrebuilt interface { + prebuiltSrcs() []string + prebuilt() *android.Prebuilt +} + +func NewPrebuiltProcMacro(hod android.HostOrDeviceSupported) (*Module, *prebuiltProcMacroDecorator) { + module, library := NewProcMacro(hod) + prebuilt := &prebuiltProcMacroDecorator{ + procMacroDecorator: library, + } + module.compiler = prebuilt + + addSrcSupplier(module, prebuilt) + + return module, prebuilt +} + var _ compiler = (*prebuiltLibraryDecorator)(nil) var _ exportedFlagsProducer = (*prebuiltLibraryDecorator)(nil) +var _ rustPrebuilt = (*prebuiltLibraryDecorator)(nil) + +var _ compiler = (*prebuiltProcMacroDecorator)(nil) +var _ exportedFlagsProducer = (*prebuiltProcMacroDecorator)(nil) +var _ rustPrebuilt = (*prebuiltProcMacroDecorator)(nil) func PrebuiltLibraryFactory() android.Module { module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported) @@ -56,7 +91,7 @@ func PrebuiltRlibFactory() android.Module { return module.Init() } -func addSrcSupplier(module android.PrebuiltInterface, prebuilt *prebuiltLibraryDecorator) { +func addSrcSupplier(module android.PrebuiltInterface, prebuilt rustPrebuilt) { srcsSupplier := func(_ android.BaseModuleContext, _ android.Module) []string { return prebuilt.prebuiltSrcs() } @@ -152,3 +187,44 @@ func (prebuilt *prebuiltLibraryDecorator) prebuiltSrcs() []string { func (prebuilt *prebuiltLibraryDecorator) prebuilt() *android.Prebuilt { return &prebuilt.Prebuilt } + +func (prebuilt *prebuiltProcMacroDecorator) prebuiltSrcs() []string { + srcs := prebuilt.Properties.Srcs + return srcs +} + +func (prebuilt *prebuiltProcMacroDecorator) prebuilt() *android.Prebuilt { + return &prebuilt.Prebuilt +} + +func (prebuilt *prebuiltProcMacroDecorator) compilerProps() []interface{} { + return append(prebuilt.procMacroDecorator.compilerProps(), + &prebuilt.Properties) +} + +func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { + prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) + prebuilt.flagExporter.setProvider(ctx) + + srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) + if len(paths) > 0 { + ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)") + } + prebuilt.baseCompiler.unstrippedOutputFile = srcPath + return srcPath +} + +func (prebuilt *prebuiltProcMacroDecorator) rustdoc(ctx ModuleContext, flags Flags, + deps PathDeps) android.OptionalPath { + + return android.OptionalPath{} +} + +func (prebuilt *prebuiltProcMacroDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { + deps = prebuilt.baseCompiler.compilerDeps(ctx, deps) + return deps +} + +func (prebuilt *prebuiltProcMacroDecorator) nativeCoverage() bool { + return false +} diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 974c096c4..f8a4bbded 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -33,6 +33,7 @@ type procMacroDecorator struct { } type procMacroInterface interface { + ProcMacro() bool } var _ compiler = (*procMacroDecorator)(nil) @@ -90,6 +91,10 @@ func (procMacro *procMacroDecorator) autoDep(ctx android.BottomUpMutatorContext) return rlibAutoDep } +func (procMacro *procMacroDecorator) ProcMacro() bool { + return true +} + func (procMacro *procMacroDecorator) everInstallable() bool { // Proc_macros are never installed return false diff --git a/rust/rust.go b/rust/rust.go index 1c718a414..d62726162 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -27,6 +27,7 @@ import ( cc_config "android/soong/cc/config" "android/soong/fuzz" "android/soong/rust/config" + "android/soong/snapshot" ) var pctx = android.NewPackageContext("android/soong/rust") @@ -806,6 +807,13 @@ func (mod *Module) Installable() *bool { return mod.Properties.Installable } +func (mod *Module) ProcMacro() bool { + if pm, ok := mod.compiler.(procMacroInterface); ok { + return pm.ProcMacro() + } + return false +} + func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain { if mod.cachedToolchain == nil { mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch()) @@ -920,12 +928,13 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo) - if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) { + if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() { // If the module has been specifically configure to not be installed then // hide from make as otherwise it will break when running inside make as the // output path to install will not be specified. Not all uninstallable // modules can be hidden from make as some are needed for resolving make - // side dependencies. + // side dependencies. In particular, proc-macros need to be captured in the + // host snapshot. mod.HideFromMake() } else if !mod.installable(apexInfo) { mod.SkipInstall() @@ -1046,7 +1055,7 @@ func (mod *Module) begin(ctx BaseModuleContext) { } func (mod *Module) Prebuilt() *android.Prebuilt { - if p, ok := mod.compiler.(*prebuiltLibraryDecorator); ok { + if p, ok := mod.compiler.(rustPrebuilt); ok { return p.prebuilt() } return nil @@ -1501,6 +1510,7 @@ func (mod *Module) disableClippy() { } var _ android.HostToolProvider = (*Module)(nil) +var _ snapshot.RelativeInstallPath = (*Module)(nil) func (mod *Module) HostToolPath() android.OptionalPath { if !mod.Host() { @@ -1508,6 +1518,10 @@ func (mod *Module) HostToolPath() android.OptionalPath { } if binary, ok := mod.compiler.(*binaryDecorator); ok { return android.OptionalPathForPath(binary.baseCompiler.path) + } else if pm, ok := mod.compiler.(*procMacroDecorator); ok { + // Even though proc-macros aren't strictly "tools", since they target the compiler + // and act as compiler plugins, we treat them similarly. + return android.OptionalPathForPath(pm.baseCompiler.path) } return android.OptionalPath{} } diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go index 6b4e12b05..1a75f3a65 100644 --- a/snapshot/host_fake_snapshot.go +++ b/snapshot/host_fake_snapshot.go @@ -114,13 +114,13 @@ func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) { if !apexInfo.IsForPlatform() { return } - path := hostBinToolPath(module) + path := hostToolPath(module) if path.Valid() && path.String() != "" { outFile := filepath.Join(c.snapshotDir, path.String()) if !seen[outFile] { seen[outFile] = true outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile)) - jsonData = append(jsonData, *hostBinJsonDesc(module)) + jsonData = append(jsonData, *hostJsonDesc(module)) } } }) diff --git a/snapshot/host_snapshot.go b/snapshot/host_snapshot.go index 09a382e6e..75b5e889f 100644 --- a/snapshot/host_snapshot.go +++ b/snapshot/host_snapshot.go @@ -19,6 +19,7 @@ import ( "fmt" "path/filepath" "sort" + "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -62,6 +63,11 @@ type hostSnapshot struct { installDir android.InstallPath } +type ProcMacro interface { + ProcMacro() bool + CrateName() string +} + func hostSnapshotFactory() android.Module { module := &hostSnapshot{} initHostToolsModule(module) @@ -94,7 +100,7 @@ func (f *hostSnapshot) CreateMetaData(ctx android.ModuleContext, fileName string // Create JSON file based on the direct dependencies ctx.VisitDirectDeps(func(dep android.Module) { - desc := hostBinJsonDesc(dep) + desc := hostJsonDesc(dep) if desc != nil { jsonData = append(jsonData, *desc) } @@ -183,7 +189,7 @@ func (f *hostSnapshot) AndroidMkEntries() []android.AndroidMkEntries { } // Get host tools path and relative install string helpers -func hostBinToolPath(m android.Module) android.OptionalPath { +func hostToolPath(m android.Module) android.OptionalPath { if provider, ok := m.(android.HostToolProvider); ok { return provider.HostToolPath() } @@ -198,18 +204,30 @@ func hostRelativePathString(m android.Module) string { return outString } -// Create JSON description for given module, only create descriptions for binary modueles which -// provide a valid HostToolPath -func hostBinJsonDesc(m android.Module) *SnapshotJsonFlags { - path := hostBinToolPath(m) +// Create JSON description for given module, only create descriptions for binary modules +// and rust_proc_macro modules which provide a valid HostToolPath +func hostJsonDesc(m android.Module) *SnapshotJsonFlags { + path := hostToolPath(m) relPath := hostRelativePathString(m) + procMacro := false + moduleStem := filepath.Base(path.String()) + crateName := "" + + if pm, ok := m.(ProcMacro); ok && pm.ProcMacro() { + procMacro = pm.ProcMacro() + moduleStem = strings.TrimSuffix(moduleStem, filepath.Ext(moduleStem)) + crateName = pm.CrateName() + } + if path.Valid() && path.String() != "" { return &SnapshotJsonFlags{ ModuleName: m.Name(), - ModuleStemName: filepath.Base(path.String()), + ModuleStemName: moduleStem, Filename: path.String(), Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames()...), RelativeInstallPath: relPath, + RustProcMacro: procMacro, + CrateName: crateName, } } return nil diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go index 79d3cf6f3..4a14f2e03 100644 --- a/snapshot/snapshot_base.go +++ b/snapshot/snapshot_base.go @@ -114,6 +114,8 @@ type SnapshotJsonFlags struct { RelativeInstallPath string `json:",omitempty"` Filename string `json:",omitempty"` ModuleStemName string `json:",omitempty"` + RustProcMacro bool `json:",omitempty"` + CrateName string `json:",omitempty"` // dependencies Required []string `json:",omitempty"`