blob: 5cf8ac7005a829fe3abf6856032a34c331fd0a55 [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// Copyright 2019 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 rust
16
17import (
18 "android/soong/android"
19)
20
21func init() {
22 android.RegisterModuleType("rust_library", RustLibraryFactory)
23 android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory)
24 android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
25 android.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
26 android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
27 android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
28
29 //TODO: Add support for generating standard shared/static libraries.
30}
31
32type VariantLibraryProperties struct {
33 Enabled *bool `android:"arch_variant"`
34}
35
36type LibraryCompilerProperties struct {
37 Rlib VariantLibraryProperties `android:"arch_variant"`
38 Dylib VariantLibraryProperties `android:"arch_variant"`
39
40 // path to the source file that is the main entry point of the program (e.g. src/lib.rs)
41 Srcs []string `android:"path,arch_variant"`
42}
43
44type LibraryMutatedProperties struct {
45 VariantName string `blueprint:"mutated"`
46
47 // Build a dylib variant
48 BuildDylib bool `blueprint:"mutated"`
49 // Build an rlib variant
50 BuildRlib bool `blueprint:"mutated"`
51
52 // This variant is a dylib
53 VariantIsDylib bool `blueprint:"mutated"`
54 // This variant is an rlib
55 VariantIsRlib bool `blueprint:"mutated"`
56}
57
58type libraryDecorator struct {
59 *baseCompiler
60
61 Properties LibraryCompilerProperties
62 MutatedProperties LibraryMutatedProperties
63 distFile android.OptionalPath
64 unstrippedOutputFile android.Path
65}
66
67type libraryInterface interface {
68 rlib() bool
69 dylib() bool
70
71 // Returns true if the build options for the module have selected a particular build type
72 buildRlib() bool
73 buildDylib() bool
74
75 // Sets a particular variant type
76 setRlib()
77 setDylib()
78}
79
80func (library *libraryDecorator) exportedDirs() []string {
81 return library.linkDirs
82}
83
84func (library *libraryDecorator) exportedDepFlags() []string {
85 return library.depFlags
86}
87
88func (library *libraryDecorator) reexportDirs(dirs ...string) {
89 library.linkDirs = android.FirstUniqueStrings(append(library.linkDirs, dirs...))
90}
91
92func (library *libraryDecorator) reexportDepFlags(flags ...string) {
93 library.depFlags = android.FirstUniqueStrings(append(library.depFlags, flags...))
94}
95
96func (library *libraryDecorator) rlib() bool {
97 return library.MutatedProperties.VariantIsRlib
98}
99
100func (library *libraryDecorator) dylib() bool {
101 return library.MutatedProperties.VariantIsDylib
102}
103
104func (library *libraryDecorator) buildRlib() bool {
105 return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
106}
107
108func (library *libraryDecorator) buildDylib() bool {
109 return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true)
110}
111
112func (library *libraryDecorator) setRlib() {
113 library.MutatedProperties.VariantIsRlib = true
114 library.MutatedProperties.VariantIsDylib = false
115}
116
117func (library *libraryDecorator) setDylib() {
118 library.MutatedProperties.VariantIsRlib = false
119 library.MutatedProperties.VariantIsDylib = true
120}
121
122var _ compiler = (*libraryDecorator)(nil)
123
124// rust_library produces all variants.
125func RustLibraryFactory() android.Module {
126 module, _ := NewRustLibrary(android.HostAndDeviceSupported)
127 return module.Init()
128}
129
130// rust_library_dylib produces a dylib.
131func RustLibraryDylibFactory() android.Module {
132 module, library := NewRustLibrary(android.HostAndDeviceSupported)
133 library.BuildOnlyDylib()
134 return module.Init()
135}
136
137// rust_library_rlib produces an rlib.
138func RustLibraryRlibFactory() android.Module {
139 module, library := NewRustLibrary(android.HostAndDeviceSupported)
140 library.BuildOnlyRlib()
141 return module.Init()
142}
143
144// rust_library_host produces all variants.
145func RustLibraryHostFactory() android.Module {
146 module, _ := NewRustLibrary(android.HostSupported)
147 return module.Init()
148}
149
150// rust_library_dylib_host produces a dylib.
151func RustLibraryDylibHostFactory() android.Module {
152 module, library := NewRustLibrary(android.HostSupported)
153 library.BuildOnlyDylib()
154 return module.Init()
155}
156
157// rust_library_rlib_host produces an rlib.
158func RustLibraryRlibHostFactory() android.Module {
159 module, library := NewRustLibrary(android.HostSupported)
160 library.BuildOnlyRlib()
161 return module.Init()
162}
163
164func (library *libraryDecorator) BuildOnlyDylib() {
165 library.MutatedProperties.BuildRlib = false
166}
167
168func (library *libraryDecorator) BuildOnlyRlib() {
169 library.MutatedProperties.BuildDylib = false
170}
171
172func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
173 module := newModule(hod, android.MultilibFirst)
174
175 library := &libraryDecorator{
176 MutatedProperties: LibraryMutatedProperties{
177 BuildDylib: true,
178 BuildRlib: true,
179 },
180 baseCompiler: NewBaseCompiler("lib", "lib64"),
181 }
182
183 module.compiler = library
184
185 return module, library
186}
187
188func (library *libraryDecorator) compilerProps() []interface{} {
189 return append(library.baseCompiler.compilerProps(),
190 &library.Properties,
191 &library.MutatedProperties)
192}
193
194func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
195 var outputFile android.WritablePath
196
197 srcPath := srcPathFromModuleSrcs(ctx, library.Properties.Srcs)
198
199 flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
200
201 if library.rlib() {
202 fileName := library.getStem(ctx) + ctx.toolchain().RlibSuffix()
203 outputFile = android.PathForModuleOut(ctx, fileName)
204
205 TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
206 } else if library.dylib() {
207 fileName := library.getStem(ctx) + ctx.toolchain().DylibSuffix()
208 outputFile = android.PathForModuleOut(ctx, fileName)
209
210 // We need prefer-dynamic for now to avoid linking in the static stdlib. See:
211 // https://github.com/rust-lang/rust/issues/19680
212 // https://github.com/rust-lang/rust/issues/34909
213 flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
214
215 TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
216 }
217
218 library.reexportDirs(deps.linkDirs...)
219 library.reexportDepFlags(deps.depFlags...)
220 library.unstrippedOutputFile = outputFile
221
222 return outputFile
223}
224
225func LibraryMutator(mctx android.BottomUpMutatorContext) {
226 if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
227 switch library := m.compiler.(type) {
228 case libraryInterface:
229 if library.buildRlib() && library.buildDylib() {
230 modules := mctx.CreateLocalVariations("rlib", "dylib")
231 rlib := modules[0].(*Module)
232 dylib := modules[1].(*Module)
233
234 rlib.compiler.(libraryInterface).setRlib()
235 dylib.compiler.(libraryInterface).setDylib()
236 } else if library.buildRlib() {
237 modules := mctx.CreateLocalVariations("rlib")
238 modules[0].(*Module).compiler.(libraryInterface).setRlib()
239 } else if library.buildDylib() {
240 modules := mctx.CreateLocalVariations("dylib")
241 modules[0].(*Module).compiler.(libraryInterface).setDylib()
242 }
243 }
244 }
245}