blob: 7cc0b2c3bb3903391ee38e8887bc3b79af286ad4 [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 "strings"
19
20 "github.com/google/blueprint"
21 "github.com/google/blueprint/proptools"
22
23 "android/soong/android"
24 "android/soong/cc"
25 "android/soong/rust/config"
26)
27
28var pctx = android.NewPackageContext("android/soong/rust")
29
30func init() {
31 // Only allow rust modules to be defined for certain projects
32 rustModuleTypes := []string{
33 "rust_binary",
34 "rust_binary_host",
35 "rust_library",
36 "rust_library_dylib",
37 "rust_library_rlib",
38 "rust_library_host",
39 "rust_library_host_dylib",
40 "rust_library_host_rlib",
41 "rust_proc_macro",
42 }
43
44 rustAllowedPaths := []string{
45 "external/rust/crates",
46 "external/crosvm",
47 "external/adhd",
48 }
49
50 android.AddNeverAllowRules(
51 android.NeverAllow().
52 NotIn(rustAllowedPaths...).
53 ModuleType(rustModuleTypes...))
54
55 android.RegisterModuleType("rust_defaults", defaultsFactory)
56 android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
57 ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
58 })
59 pctx.Import("android/soong/rust/config")
60}
61
62type Flags struct {
63 GlobalFlags []string // Flags that apply globally
64 RustFlags []string // Flags that apply to rust
65 LinkFlags []string // Flags that apply to linker
66 RustFlagsDeps android.Paths // Files depended on by compiler flags
67 Toolchain config.Toolchain
68}
69
70type BaseProperties struct {
71 AndroidMkRlibs []string
72 AndroidMkDylibs []string
73 AndroidMkProcMacroLibs []string
74 AndroidMkSharedLibs []string
75 AndroidMkStaticLibs []string
76}
77
78type Module struct {
79 android.ModuleBase
80 android.DefaultableModuleBase
81
82 Properties BaseProperties
83
84 hod android.HostOrDeviceSupported
85 multilib android.Multilib
86
87 compiler compiler
88 cachedToolchain config.Toolchain
89 subAndroidMkOnce map[subAndroidMkProvider]bool
90 outputFile android.OptionalPath
91}
92
93type Deps struct {
94 Dylibs []string
95 Rlibs []string
96 ProcMacros []string
97 SharedLibs []string
98 StaticLibs []string
99
100 CrtBegin, CrtEnd string
101}
102
103type PathDeps struct {
104 DyLibs RustLibraries
105 RLibs RustLibraries
106 SharedLibs android.Paths
107 StaticLibs android.Paths
108 ProcMacros RustLibraries
109 linkDirs []string
110 depFlags []string
111 //ReexportedDeps android.Paths
112}
113
114type RustLibraries []RustLibrary
115
116type RustLibrary struct {
117 Path android.Path
118 CrateName string
119}
120
121type compiler interface {
122 compilerFlags(ctx ModuleContext, flags Flags) Flags
123 compilerProps() []interface{}
124 compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path
125 compilerDeps(ctx DepsContext, deps Deps) Deps
126 crateName() string
127
128 install(ctx ModuleContext, path android.Path)
129 relativeInstallPath() string
130}
131
132func defaultsFactory() android.Module {
133 return DefaultsFactory()
134}
135
136type Defaults struct {
137 android.ModuleBase
138 android.DefaultsModuleBase
139}
140
141func DefaultsFactory(props ...interface{}) android.Module {
142 module := &Defaults{}
143
144 module.AddProperties(props...)
145 module.AddProperties(
146 &BaseProperties{},
147 &BaseCompilerProperties{},
148 &BinaryCompilerProperties{},
149 &LibraryCompilerProperties{},
150 &ProcMacroCompilerProperties{},
151 &PrebuiltProperties{},
152 )
153
154 android.InitDefaultsModule(module)
155 return module
156}
157
158func (mod *Module) CrateName() string {
159 if mod.compiler != nil && mod.compiler.crateName() != "" {
160 return mod.compiler.crateName()
161 }
162 // Default crate names replace '-' in the name to '_'
163 return strings.Replace(mod.BaseModuleName(), "-", "_", -1)
164}
165
166func (mod *Module) Init() android.Module {
167 mod.AddProperties(&mod.Properties)
168
169 if mod.compiler != nil {
170 mod.AddProperties(mod.compiler.compilerProps()...)
171 }
172 android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
173
174 android.InitDefaultableModule(mod)
175
Ivan Lozanode252912019-09-06 15:29:52 -0700176 // Explicitly disable unsupported targets.
177 android.AddLoadHook(mod, func(ctx android.LoadHookContext) {
178 disableTargets := struct {
179 Target struct {
180 Darwin struct {
181 Enabled *bool
182 }
183 Linux_bionic struct {
184 Enabled *bool
185 }
186 }
187 }{}
188 disableTargets.Target.Darwin.Enabled = proptools.BoolPtr(false)
189 disableTargets.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
190
191 ctx.AppendProperties(&disableTargets)
192 })
193
Ivan Lozanoffee3342019-08-27 12:03:00 -0700194 return mod
195}
196
197func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
198 return &Module{
199 hod: hod,
200 multilib: multilib,
201 }
202}
203func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
204 module := newBaseModule(hod, multilib)
205 return module
206}
207
208type ModuleContext interface {
209 android.ModuleContext
210 ModuleContextIntf
211}
212
213type BaseModuleContext interface {
214 android.BaseModuleContext
215 ModuleContextIntf
216}
217
218type DepsContext interface {
219 android.BottomUpMutatorContext
220 ModuleContextIntf
221}
222
223type ModuleContextIntf interface {
224 toolchain() config.Toolchain
225 baseModuleName() string
226 CrateName() string
227}
228
229type depsContext struct {
230 android.BottomUpMutatorContext
231 moduleContextImpl
232}
233
234type moduleContext struct {
235 android.ModuleContext
236 moduleContextImpl
237}
238
239type moduleContextImpl struct {
240 mod *Module
241 ctx BaseModuleContext
242}
243
244func (ctx *moduleContextImpl) toolchain() config.Toolchain {
245 return ctx.mod.toolchain(ctx.ctx)
246}
247
248func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
249 if mod.cachedToolchain == nil {
250 mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
251 }
252 return mod.cachedToolchain
253}
254
255func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
256}
257
258func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
259 ctx := &moduleContext{
260 ModuleContext: actx,
261 moduleContextImpl: moduleContextImpl{
262 mod: mod,
263 },
264 }
265 ctx.ctx = ctx
266
267 toolchain := mod.toolchain(ctx)
268
269 if !toolchain.Supported() {
270 // This toolchain's unsupported, there's nothing to do for this mod.
271 return
272 }
273
274 deps := mod.depsToPaths(ctx)
275 flags := Flags{
276 Toolchain: toolchain,
277 }
278
279 if mod.compiler != nil {
280 flags = mod.compiler.compilerFlags(ctx, flags)
281 outputFile := mod.compiler.compile(ctx, flags, deps)
282 mod.outputFile = android.OptionalPathForPath(outputFile)
283 mod.compiler.install(ctx, mod.outputFile.Path())
284 }
285}
286
287func (mod *Module) deps(ctx DepsContext) Deps {
288 deps := Deps{}
289
290 if mod.compiler != nil {
291 deps = mod.compiler.compilerDeps(ctx, deps)
292 }
293
294 deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
295 deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
296 deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
297 deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
298 deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
299
300 return deps
301
302}
303
304func (ctx *moduleContextImpl) baseModuleName() string {
305 return ctx.mod.ModuleBase.BaseModuleName()
306}
307
308func (ctx *moduleContextImpl) CrateName() string {
309 return ctx.mod.CrateName()
310}
311
312type dependencyTag struct {
313 blueprint.BaseDependencyTag
314 name string
315 library bool
316 proc_macro bool
317}
318
319var (
320 rlibDepTag = dependencyTag{name: "rlibTag", library: true}
321 dylibDepTag = dependencyTag{name: "dylib", library: true}
322 procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
323)
324
325func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
326 var depPaths PathDeps
327
328 directRlibDeps := []*Module{}
329 directDylibDeps := []*Module{}
330 directProcMacroDeps := []*Module{}
331 directSharedLibDeps := []*(cc.Module){}
332 directStaticLibDeps := []*(cc.Module){}
333
334 ctx.VisitDirectDeps(func(dep android.Module) {
335 depName := ctx.OtherModuleName(dep)
336 depTag := ctx.OtherModuleDependencyTag(dep)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700337
338 if rustDep, ok := dep.(*Module); ok {
339 //Handle Rust Modules
Ivan Lozano70e0a072019-09-13 14:23:15 -0700340
341 if rustDep.Target().Os != ctx.Os() {
342 ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
343 return
344 }
345 if rustDep.Target().Arch.ArchType != ctx.Arch().ArchType {
346 ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
347 return
348 }
349
Ivan Lozanoffee3342019-08-27 12:03:00 -0700350 linkFile := rustDep.outputFile
351 if !linkFile.Valid() {
352 ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
353 }
354
355 switch depTag {
356 case dylibDepTag:
357 dylib, ok := rustDep.compiler.(libraryInterface)
358 if !ok || !dylib.dylib() {
359 ctx.ModuleErrorf("mod %q not an dylib library", depName)
360 return
361 }
362 directDylibDeps = append(directDylibDeps, rustDep)
363 mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, depName)
364 case rlibDepTag:
365 rlib, ok := rustDep.compiler.(libraryInterface)
366 if !ok || !rlib.rlib() {
367 ctx.ModuleErrorf("mod %q not an rlib library", depName)
368 return
369 }
370 directRlibDeps = append(directRlibDeps, rustDep)
371 mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName)
372 case procMacroDepTag:
373 directProcMacroDeps = append(directProcMacroDeps, rustDep)
374 mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, depName)
375 }
376
377 //Append the dependencies exportedDirs
378 if lib, ok := rustDep.compiler.(*libraryDecorator); ok {
379 depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedDirs()...)
380 depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
381 } else if procMacro, ok := rustDep.compiler.(*libraryDecorator); ok {
382 depPaths.linkDirs = append(depPaths.linkDirs, procMacro.exportedDirs()...)
383 depPaths.depFlags = append(depPaths.depFlags, procMacro.exportedDepFlags()...)
384 }
385
386 // Append this dependencies output to this mod's linkDirs so they can be exported to dependencies
387 // This can be probably be refactored by defining a common exporter interface similar to cc's
388 if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
389 linkDir := linkPathFromFilePath(linkFile.Path())
390 if lib, ok := mod.compiler.(*libraryDecorator); ok {
391 lib.linkDirs = append(lib.linkDirs, linkDir)
392 } else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok {
393 procMacro.linkDirs = append(procMacro.linkDirs, linkDir)
394 }
395 }
396
397 } else if ccDep, ok := dep.(*cc.Module); ok {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700398 //Handle C dependencies
Ivan Lozano70e0a072019-09-13 14:23:15 -0700399
400 if ccDep.Target().Os != ctx.Os() {
401 ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
402 return
403 }
404 if ccDep.Target().Arch.ArchType != ctx.Arch().ArchType {
405 ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
406 return
407 }
408
Ivan Lozanoffee3342019-08-27 12:03:00 -0700409 linkFile := ccDep.OutputFile()
410 linkPath := linkPathFromFilePath(linkFile.Path())
411 libName := libNameFromFilePath(linkFile.Path())
412 if !linkFile.Valid() {
413 ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
414 }
415
416 exportDep := false
417
418 switch depTag {
419 case cc.StaticDepTag():
420 depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
421 depPaths.depFlags = append(depPaths.depFlags, "-l"+libName)
422 directStaticLibDeps = append(directStaticLibDeps, ccDep)
423 mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
424 case cc.SharedDepTag():
425 depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
426 depPaths.depFlags = append(depPaths.depFlags, "-l"+libName)
427 directSharedLibDeps = append(directSharedLibDeps, ccDep)
428 mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
429 exportDep = true
430 }
431
432 // Make sure these dependencies are propagated
433 if lib, ok := mod.compiler.(*libraryDecorator); ok && (exportDep || lib.rlib()) {
434 lib.linkDirs = append(lib.linkDirs, linkPath)
435 lib.depFlags = append(lib.depFlags, "-l"+libName)
436 } else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok && exportDep {
437 procMacro.linkDirs = append(procMacro.linkDirs, linkPath)
438 procMacro.depFlags = append(procMacro.depFlags, "-l"+libName)
439 }
440
441 }
442 })
443
444 var rlibDepFiles RustLibraries
445 for _, dep := range directRlibDeps {
446 rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
447 }
448 var dylibDepFiles RustLibraries
449 for _, dep := range directDylibDeps {
450 dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
451 }
452 var procMacroDepFiles RustLibraries
453 for _, dep := range directProcMacroDeps {
454 procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
455 }
456
457 var staticLibDepFiles android.Paths
458 for _, dep := range directStaticLibDeps {
459 staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
460 }
461
462 var sharedLibDepFiles android.Paths
463 for _, dep := range directSharedLibDeps {
464 sharedLibDepFiles = append(sharedLibDepFiles, dep.OutputFile().Path())
465 }
466
467 depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
468 depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
469 depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibDepFiles...)
470 depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
471 depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
472
473 // Dedup exported flags from dependencies
474 depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
475 depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
476
477 return depPaths
478}
479
480func linkPathFromFilePath(filepath android.Path) string {
481 return strings.Split(filepath.String(), filepath.Base())[0]
482}
483func libNameFromFilePath(filepath android.Path) string {
484 libName := strings.Split(filepath.Base(), filepath.Ext())[0]
485 if strings.Contains(libName, "lib") {
486 libName = strings.Split(libName, "lib")[1]
487 }
488 return libName
489}
490func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
491 ctx := &depsContext{
492 BottomUpMutatorContext: actx,
493 moduleContextImpl: moduleContextImpl{
494 mod: mod,
495 },
496 }
497 ctx.ctx = ctx
498
499 deps := mod.deps(ctx)
500
501 actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, deps.Rlibs...)
502 actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "dylib"}}, dylibDepTag, deps.Dylibs...)
503
504 ccDepVariations := []blueprint.Variation{}
505 ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "version", Variation: ""})
506 if !mod.Host() {
507 ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "image", Variation: "core"})
508 }
509 actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...)
510 actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...)
511 actx.AddDependency(mod, procMacroDepTag, deps.ProcMacros...)
512}
513
514func (mod *Module) Name() string {
515 name := mod.ModuleBase.Name()
516 if p, ok := mod.compiler.(interface {
517 Name(string) string
518 }); ok {
519 name = p.Name(name)
520 }
521 return name
522}
523
524var Bool = proptools.Bool
525var BoolDefault = proptools.BoolDefault
526var String = proptools.String
527var StringPtr = proptools.StringPtr