blob: bf863bb671b6f6497fa3a2d3fa31355a28a7e906 [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 (
Ivan Lozanoad8b18b2019-10-31 19:38:29 -070018 "regexp"
19 "strings"
20
Ivan Lozanoffee3342019-08-27 12:03:00 -070021 "android/soong/android"
Ivan Lozano88f2b1c2019-11-21 14:35:20 -080022 "android/soong/rust/config"
Ivan Lozanoffee3342019-08-27 12:03:00 -070023)
24
25func init() {
26 android.RegisterModuleType("rust_library", RustLibraryFactory)
27 android.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory)
28 android.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
29 android.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
30 android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
31 android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
Ivan Lozano52767be2019-10-18 14:49:46 -070032 android.RegisterModuleType("rust_library_shared", RustLibrarySharedFactory)
33 android.RegisterModuleType("rust_library_static", RustLibraryStaticFactory)
34 android.RegisterModuleType("rust_library_host_shared", RustLibrarySharedHostFactory)
35 android.RegisterModuleType("rust_library_host_static", RustLibraryStaticHostFactory)
Ivan Lozanoffee3342019-08-27 12:03:00 -070036}
37
38type VariantLibraryProperties struct {
39 Enabled *bool `android:"arch_variant"`
40}
41
42type LibraryCompilerProperties struct {
Ivan Lozano52767be2019-10-18 14:49:46 -070043 Rlib VariantLibraryProperties `android:"arch_variant"`
44 Dylib VariantLibraryProperties `android:"arch_variant"`
45 Shared VariantLibraryProperties `android:"arch_variant"`
46 Static VariantLibraryProperties `android:"arch_variant"`
Ivan Lozanoffee3342019-08-27 12:03:00 -070047
48 // path to the source file that is the main entry point of the program (e.g. src/lib.rs)
49 Srcs []string `android:"path,arch_variant"`
Ivan Lozano52767be2019-10-18 14:49:46 -070050
51 // path to include directories to pass to cc_* modules, only relevant for static/shared variants.
52 Include_dirs []string `android:"path,arch_variant"`
Ivan Lozanoffee3342019-08-27 12:03:00 -070053}
54
55type LibraryMutatedProperties struct {
Ivan Lozanoffee3342019-08-27 12:03:00 -070056 // Build a dylib variant
57 BuildDylib bool `blueprint:"mutated"`
58 // Build an rlib variant
59 BuildRlib bool `blueprint:"mutated"`
Ivan Lozano52767be2019-10-18 14:49:46 -070060 // Build a shared library variant
61 BuildShared bool `blueprint:"mutated"`
62 // Build a static library variant
63 BuildStatic bool `blueprint:"mutated"`
Ivan Lozanoffee3342019-08-27 12:03:00 -070064
65 // This variant is a dylib
66 VariantIsDylib bool `blueprint:"mutated"`
67 // This variant is an rlib
68 VariantIsRlib bool `blueprint:"mutated"`
Ivan Lozano52767be2019-10-18 14:49:46 -070069 // This variant is a shared library
70 VariantIsShared bool `blueprint:"mutated"`
71 // This variant is a static library
72 VariantIsStatic bool `blueprint:"mutated"`
Ivan Lozanoffee3342019-08-27 12:03:00 -070073}
74
75type libraryDecorator struct {
76 *baseCompiler
77
78 Properties LibraryCompilerProperties
79 MutatedProperties LibraryMutatedProperties
80 distFile android.OptionalPath
81 unstrippedOutputFile android.Path
Ivan Lozanoe0833b12019-11-06 19:15:49 -080082 includeDirs android.Paths
Ivan Lozanoffee3342019-08-27 12:03:00 -070083}
84
85type libraryInterface interface {
86 rlib() bool
87 dylib() bool
Ivan Lozano52767be2019-10-18 14:49:46 -070088 static() bool
89 shared() bool
Ivan Lozanoffee3342019-08-27 12:03:00 -070090
91 // Returns true if the build options for the module have selected a particular build type
92 buildRlib() bool
93 buildDylib() bool
Ivan Lozano52767be2019-10-18 14:49:46 -070094 buildShared() bool
95 buildStatic() bool
Ivan Lozanoffee3342019-08-27 12:03:00 -070096
97 // Sets a particular variant type
98 setRlib()
99 setDylib()
Ivan Lozano52767be2019-10-18 14:49:46 -0700100 setShared()
101 setStatic()
102
103 // Build a specific library variant
104 BuildOnlyRlib()
105 BuildOnlyDylib()
106 BuildOnlyStatic()
107 BuildOnlyShared()
Ivan Lozanoffee3342019-08-27 12:03:00 -0700108}
109
110func (library *libraryDecorator) exportedDirs() []string {
111 return library.linkDirs
112}
113
114func (library *libraryDecorator) exportedDepFlags() []string {
115 return library.depFlags
116}
117
118func (library *libraryDecorator) reexportDirs(dirs ...string) {
119 library.linkDirs = android.FirstUniqueStrings(append(library.linkDirs, dirs...))
120}
121
122func (library *libraryDecorator) reexportDepFlags(flags ...string) {
123 library.depFlags = android.FirstUniqueStrings(append(library.depFlags, flags...))
124}
125
126func (library *libraryDecorator) rlib() bool {
127 return library.MutatedProperties.VariantIsRlib
128}
129
130func (library *libraryDecorator) dylib() bool {
131 return library.MutatedProperties.VariantIsDylib
132}
133
Ivan Lozano52767be2019-10-18 14:49:46 -0700134func (library *libraryDecorator) shared() bool {
135 return library.MutatedProperties.VariantIsShared
136}
137
138func (library *libraryDecorator) static() bool {
139 return library.MutatedProperties.VariantIsStatic
140}
141
Ivan Lozanoffee3342019-08-27 12:03:00 -0700142func (library *libraryDecorator) buildRlib() bool {
143 return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
144}
145
146func (library *libraryDecorator) buildDylib() bool {
147 return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true)
148}
149
Ivan Lozano52767be2019-10-18 14:49:46 -0700150func (library *libraryDecorator) buildShared() bool {
151 return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true)
152}
153
154func (library *libraryDecorator) buildStatic() bool {
155 return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true)
156}
157
Ivan Lozanoffee3342019-08-27 12:03:00 -0700158func (library *libraryDecorator) setRlib() {
159 library.MutatedProperties.VariantIsRlib = true
160 library.MutatedProperties.VariantIsDylib = false
Ivan Lozano52767be2019-10-18 14:49:46 -0700161 library.MutatedProperties.VariantIsStatic = false
162 library.MutatedProperties.VariantIsShared = false
Ivan Lozanoffee3342019-08-27 12:03:00 -0700163}
164
165func (library *libraryDecorator) setDylib() {
166 library.MutatedProperties.VariantIsRlib = false
167 library.MutatedProperties.VariantIsDylib = true
Ivan Lozano52767be2019-10-18 14:49:46 -0700168 library.MutatedProperties.VariantIsStatic = false
169 library.MutatedProperties.VariantIsShared = false
170}
171
172func (library *libraryDecorator) setShared() {
173 library.MutatedProperties.VariantIsStatic = false
174 library.MutatedProperties.VariantIsShared = true
175 library.MutatedProperties.VariantIsRlib = false
176 library.MutatedProperties.VariantIsDylib = false
177}
178
179func (library *libraryDecorator) setStatic() {
180 library.MutatedProperties.VariantIsStatic = true
181 library.MutatedProperties.VariantIsShared = false
182 library.MutatedProperties.VariantIsRlib = false
183 library.MutatedProperties.VariantIsDylib = false
Ivan Lozanoffee3342019-08-27 12:03:00 -0700184}
185
186var _ compiler = (*libraryDecorator)(nil)
Ivan Lozano52767be2019-10-18 14:49:46 -0700187var _ libraryInterface = (*libraryDecorator)(nil)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700188
189// rust_library produces all variants.
190func RustLibraryFactory() android.Module {
191 module, _ := NewRustLibrary(android.HostAndDeviceSupported)
192 return module.Init()
193}
194
195// rust_library_dylib produces a dylib.
196func RustLibraryDylibFactory() android.Module {
197 module, library := NewRustLibrary(android.HostAndDeviceSupported)
198 library.BuildOnlyDylib()
199 return module.Init()
200}
201
202// rust_library_rlib produces an rlib.
203func RustLibraryRlibFactory() android.Module {
204 module, library := NewRustLibrary(android.HostAndDeviceSupported)
205 library.BuildOnlyRlib()
206 return module.Init()
207}
208
Ivan Lozano52767be2019-10-18 14:49:46 -0700209// rust_library_shared produces a shared library.
210func RustLibrarySharedFactory() android.Module {
211 module, library := NewRustLibrary(android.HostAndDeviceSupported)
212 library.BuildOnlyShared()
213 return module.Init()
214}
215
216// rust_library_static produces a static library.
217func RustLibraryStaticFactory() android.Module {
218 module, library := NewRustLibrary(android.HostAndDeviceSupported)
219 library.BuildOnlyStatic()
220 return module.Init()
221}
222
Ivan Lozanoffee3342019-08-27 12:03:00 -0700223// rust_library_host produces all variants.
224func RustLibraryHostFactory() android.Module {
225 module, _ := NewRustLibrary(android.HostSupported)
226 return module.Init()
227}
228
229// rust_library_dylib_host produces a dylib.
230func RustLibraryDylibHostFactory() android.Module {
231 module, library := NewRustLibrary(android.HostSupported)
232 library.BuildOnlyDylib()
233 return module.Init()
234}
235
236// rust_library_rlib_host produces an rlib.
237func RustLibraryRlibHostFactory() android.Module {
238 module, library := NewRustLibrary(android.HostSupported)
239 library.BuildOnlyRlib()
240 return module.Init()
241}
242
Ivan Lozano52767be2019-10-18 14:49:46 -0700243// rust_library_static_host produces a static library.
244func RustLibraryStaticHostFactory() android.Module {
245 module, library := NewRustLibrary(android.HostSupported)
246 library.BuildOnlyStatic()
247 return module.Init()
248}
249
250// rust_library_shared_host produces an shared library.
251func RustLibrarySharedHostFactory() android.Module {
252 module, library := NewRustLibrary(android.HostSupported)
253 library.BuildOnlyShared()
254 return module.Init()
255}
256
Ivan Lozanoffee3342019-08-27 12:03:00 -0700257func (library *libraryDecorator) BuildOnlyDylib() {
258 library.MutatedProperties.BuildRlib = false
Ivan Lozano52767be2019-10-18 14:49:46 -0700259 library.MutatedProperties.BuildShared = false
260 library.MutatedProperties.BuildStatic = false
261
Ivan Lozanoffee3342019-08-27 12:03:00 -0700262}
263
264func (library *libraryDecorator) BuildOnlyRlib() {
265 library.MutatedProperties.BuildDylib = false
Ivan Lozano52767be2019-10-18 14:49:46 -0700266 library.MutatedProperties.BuildShared = false
267 library.MutatedProperties.BuildStatic = false
268}
269
270func (library *libraryDecorator) BuildOnlyStatic() {
271 library.MutatedProperties.BuildShared = false
272 library.MutatedProperties.BuildRlib = false
273 library.MutatedProperties.BuildDylib = false
274
275}
276
277func (library *libraryDecorator) BuildOnlyShared() {
278 library.MutatedProperties.BuildStatic = false
279 library.MutatedProperties.BuildRlib = false
280 library.MutatedProperties.BuildDylib = false
Ivan Lozanoffee3342019-08-27 12:03:00 -0700281}
282
283func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
284 module := newModule(hod, android.MultilibFirst)
285
286 library := &libraryDecorator{
287 MutatedProperties: LibraryMutatedProperties{
Ivan Lozano52767be2019-10-18 14:49:46 -0700288 BuildDylib: true,
289 BuildRlib: true,
290 BuildShared: true,
291 BuildStatic: true,
Ivan Lozanoffee3342019-08-27 12:03:00 -0700292 },
Chih-Hung Hsieh9a4a7ba2019-12-12 19:36:05 -0800293 baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
Ivan Lozanoffee3342019-08-27 12:03:00 -0700294 }
295
296 module.compiler = library
297
298 return module, library
299}
300
301func (library *libraryDecorator) compilerProps() []interface{} {
302 return append(library.baseCompiler.compilerProps(),
303 &library.Properties,
304 &library.MutatedProperties)
305}
306
Ivan Lozanof1c84332019-09-20 11:00:37 -0700307func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
Ivan Lozano88f2b1c2019-11-21 14:35:20 -0800308
309 // TODO(b/144861059) Remove if C libraries support dylib linkage in the future.
310 if !ctx.Host() && (library.static() || library.shared()) {
311 library.setNoStdlibs()
312 for _, stdlib := range config.Stdlibs {
313 deps.Rlibs = append(deps.Rlibs, stdlib+".static")
314 }
315 }
316
Ivan Lozanof1c84332019-09-20 11:00:37 -0700317 deps = library.baseCompiler.compilerDeps(ctx, deps)
318
Ivan Lozano52767be2019-10-18 14:49:46 -0700319 if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
Ivan Lozanof1c84332019-09-20 11:00:37 -0700320 deps = library.baseCompiler.bionicDeps(ctx, deps)
Ivan Lozano12ee9ca2020-04-07 13:19:44 -0400321 deps.CrtBegin = "crtbegin_so"
322 deps.CrtEnd = "crtend_so"
Ivan Lozanof1c84332019-09-20 11:00:37 -0700323 }
324
325 return deps
326}
Ivan Lozanoe0833b12019-11-06 19:15:49 -0800327func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
Matthew Maurer22cef962020-01-13 16:31:13 -0800328 flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.baseModuleName())
Ivan Lozanoe0833b12019-11-06 19:15:49 -0800329 flags = library.baseCompiler.compilerFlags(ctx, flags)
330 if library.shared() || library.static() {
331 library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
332 }
333 return flags
334}
Ivan Lozanof1c84332019-09-20 11:00:37 -0700335
Ivan Lozanoffee3342019-08-27 12:03:00 -0700336func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
337 var outputFile android.WritablePath
338
339 srcPath := srcPathFromModuleSrcs(ctx, library.Properties.Srcs)
340
341 flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
342
Matthew Maurer46c46cc2020-01-13 16:34:34 -0800343 if library.dylib() {
Ivan Lozano52767be2019-10-18 14:49:46 -0700344 // We need prefer-dynamic for now to avoid linking in the static stdlib. See:
345 // https://github.com/rust-lang/rust/issues/19680
346 // https://github.com/rust-lang/rust/issues/34909
347 flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
348 }
349
Ivan Lozanoffee3342019-08-27 12:03:00 -0700350 if library.rlib() {
351 fileName := library.getStem(ctx) + ctx.toolchain().RlibSuffix()
352 outputFile = android.PathForModuleOut(ctx, fileName)
353
354 TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
355 } else if library.dylib() {
356 fileName := library.getStem(ctx) + ctx.toolchain().DylibSuffix()
357 outputFile = android.PathForModuleOut(ctx, fileName)
358
Ivan Lozanoffee3342019-08-27 12:03:00 -0700359 TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
Ivan Lozano52767be2019-10-18 14:49:46 -0700360 } else if library.static() {
361 fileName := library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
362 outputFile = android.PathForModuleOut(ctx, fileName)
363
364 TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
365 } else if library.shared() {
366 fileName := library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
367 outputFile = android.PathForModuleOut(ctx, fileName)
368
369 TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700370 }
371
Ivan Lozano52767be2019-10-18 14:49:46 -0700372 if library.rlib() || library.dylib() {
373 library.reexportDirs(deps.linkDirs...)
374 library.reexportDepFlags(deps.depFlags...)
375 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700376 library.unstrippedOutputFile = outputFile
377
378 return outputFile
379}
380
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700381func (library *libraryDecorator) getStem(ctx ModuleContext) string {
382 stem := library.baseCompiler.getStemWithoutSuffix(ctx)
383 validateLibraryStem(ctx, stem, library.crateName())
384
385 return stem + String(library.baseCompiler.Properties.Suffix)
386}
387
388var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
389
390func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
391 if crate_name == "" {
392 ctx.PropertyErrorf("crate_name", "crate_name must be defined.")
393 }
394
395 // crate_names are used for the library output file, and rustc expects these
396 // to be alphanumeric with underscores allowed.
397 if validCrateName.MatchString(crate_name) {
398 ctx.PropertyErrorf("crate_name",
399 "library crate_names must be alphanumeric with underscores allowed")
400 }
401
402 // Libraries are expected to begin with "lib" followed by the crate_name
403 if !strings.HasPrefix(filename, "lib"+crate_name) {
404 ctx.ModuleErrorf("Invalid name or stem property; library filenames must start with lib<crate_name>")
405 }
406}
407
Ivan Lozanoffee3342019-08-27 12:03:00 -0700408func LibraryMutator(mctx android.BottomUpMutatorContext) {
409 if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
410 switch library := m.compiler.(type) {
411 case libraryInterface:
Ivan Lozanoffee3342019-08-27 12:03:00 -0700412
Ivan Lozano52767be2019-10-18 14:49:46 -0700413 // We only build the rust library variants here. This assumes that
414 // LinkageMutator runs first and there's an empty variant
415 // if rust variants are required.
416 if !library.static() && !library.shared() {
417 if library.buildRlib() && library.buildDylib() {
418 modules := mctx.CreateLocalVariations("rlib", "dylib")
419 rlib := modules[0].(*Module)
420 dylib := modules[1].(*Module)
421
422 rlib.compiler.(libraryInterface).setRlib()
423 dylib.compiler.(libraryInterface).setDylib()
424 } else if library.buildRlib() {
425 modules := mctx.CreateLocalVariations("rlib")
426 modules[0].(*Module).compiler.(libraryInterface).setRlib()
427 } else if library.buildDylib() {
428 modules := mctx.CreateLocalVariations("dylib")
429 modules[0].(*Module).compiler.(libraryInterface).setDylib()
430 }
Ivan Lozanoffee3342019-08-27 12:03:00 -0700431 }
432 }
433 }
434}