• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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