1// Copyright (C) 2021 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package aidl 16 17import ( 18 "android/soong/android" 19 "android/soong/rust" 20 21 "strings" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25) 26 27var ( 28 aidlRustGlueRule = pctx.StaticRule("aidlRustGlueRule", blueprint.RuleParams{ 29 Command: `${aidlRustGlueCmd} ${out} ${root} ${in} ${imports}`, 30 CommandDeps: []string{"${aidlRustGlueCmd}"}, 31 }, "root", "imports") 32) 33 34type aidlRustSourceProviderProperties struct { 35 SourceGen string `android:"path"` 36 Imports []string 37 Version string 38 AidlInterfaceName string 39} 40 41type aidlRustSourceProvider struct { 42 *rust.BaseSourceProvider 43 44 properties aidlRustSourceProviderProperties 45} 46 47var aidlRustSourceTag = struct { 48 blueprint.DependencyTag 49}{} 50 51func (sp *aidlRustSourceProvider) GenerateSource(ctx rust.ModuleContext, _ rust.PathDeps) android.Path { 52 sourceStem := proptools.String(sp.BaseSourceProvider.Properties.Source_stem) 53 topLevelOutputFile := android.PathForModuleOut(ctx, sourceStem+".rs") 54 55 aidlGenModule := ctx.GetDirectDepWithTag(sp.properties.SourceGen, aidlRustSourceTag) 56 // Find the gen directory for the source module 57 srcGenDir := aidlGenModule.(*aidlGenRule).genOutDir 58 srcPaths := aidlGenModule.(*aidlGenRule).genOutputs.Paths() 59 60 // In Rust, we import our dependency crates into `mangled`: 61 // use dependency::mangled::*; 62 // so we can use the crate:: Rust path prefix to refer to 63 // both crate-local and imported paths (from dependencies) 64 importFlags := make([]string, len(sp.properties.Imports)) 65 for i, dep := range trimVersionSuffixInList(sp.properties.Imports) { 66 importFlags[i] = "-I" + fixRustName(dep) 67 } 68 69 // In Rust, we need to do some extra post-processing: 70 // emit a top-level foo.rs that includes all the generated .rs 71 // files verbatim ("glued" together). The generated glue file 72 // replicates the AIDL package hierarchy from the input 73 // .aidl files in two ways: 74 // * 1:1 mapping in the crate::aidl namespace, used by downstream users 75 // * mangled in the crate::mangled namespace, used internally 76 // to resolve AIDL package paths between dependencies 77 ctx.Build(pctx, android.BuildParams{ 78 Rule: aidlRustGlueRule, 79 Inputs: srcPaths, 80 Output: topLevelOutputFile, 81 Args: map[string]string{ 82 "root": srcGenDir.String(), 83 "imports": strings.Join(importFlags, " "), 84 }, 85 }) 86 87 sp.BaseSourceProvider.OutputFiles = android.Paths{topLevelOutputFile} 88 return topLevelOutputFile 89} 90 91func (sp *aidlRustSourceProvider) SourceProviderProps() []interface{} { 92 return append(sp.BaseSourceProvider.SourceProviderProps(), 93 &sp.properties) 94} 95 96func (sp *aidlRustSourceProvider) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps { 97 deps = sp.BaseSourceProvider.SourceProviderDeps(ctx, deps) 98 deps.Rustlibs = append(deps.Rustlibs, "libbinder_rs") 99 deps.Rustlibs = append(deps.Rustlibs, wrap("", getImportsWithVersion(ctx, sp.properties.AidlInterfaceName, sp.properties.Version), "-"+langRust)...) 100 deps.Rustlibs = append(deps.Rustlibs, "libstatic_assertions") 101 deps.ProcMacros = append(deps.ProcMacros, "libasync_trait") 102 // Add a depencency to the source module (*-rust-source) directly via `ctx` because 103 // the source module is specific to aidlRustSourceProvider and we don't want the rust module 104 // to know about it. 105 ctx.AddDependency(ctx.Module(), aidlRustSourceTag, sp.properties.SourceGen) 106 107 return deps 108} 109 110func (sp *aidlRustSourceProvider) AndroidMk(ctx rust.AndroidMkContext, ret *android.AndroidMkEntries) { 111 ctx.SubAndroidMk(ret, sp.BaseSourceProvider) 112 ret.ExtraEntries = append(ret.ExtraEntries, 113 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 114 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) 115 }) 116} 117 118func aidlRustLibraryFactory() android.Module { 119 sourceProvider := &aidlRustSourceProvider{ 120 BaseSourceProvider: rust.NewSourceProvider(), 121 properties: aidlRustSourceProviderProperties{}, 122 } 123 124 module := rust.NewSourceProviderModule(android.HostAndDeviceSupported, sourceProvider, false, false) 125 return module.Init() 126} 127