blob: e71cea058ab88678745d1d24d1482c6d0f9b8d41 [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 Lozano1776a2a2020-11-11 10:59:52 -050018 "path/filepath"
Ivan Lozanoffee3342019-08-27 12:03:00 -070019 "strings"
20
21 "github.com/google/blueprint"
22
23 "android/soong/android"
Ivan Lozano0a468a42024-05-13 21:03:34 -040024 "android/soong/cc"
ThiƩbaud Weksteen71512f32020-11-03 15:17:51 +010025 "android/soong/rust/config"
Ivan Lozanoffee3342019-08-27 12:03:00 -070026)
27
28var (
Wen-yi Chu41326c12023-09-22 03:58:59 +000029 _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +000030 rustc = pctx.AndroidStaticRule("rustc",
31 blueprint.RuleParams{
32 Command: "$envVars $rustcCmd " +
Ivan Lozanof4589012024-11-20 22:18:11 +000033 "-C linker=${RustcLinkerCmd} " +
34 "-C link-args=\"--android-clang-bin=${config.ClangCmd} ${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
Wen-yi Chu41326c12023-09-22 03:58:59 +000035 "--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
Ivan Lozanocfeec1c2024-03-28 19:27:24 +000036 " && grep ^$out: $out.d.raw > $out.d",
Ivan Lozanof4589012024-11-20 22:18:11 +000037 CommandDeps: []string{"$rustcCmd", "${RustcLinkerCmd}", "${config.ClangCmd}"},
Wen-yi Chu41326c12023-09-22 03:58:59 +000038 // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
39 // Rustc emits unneeded dependency lines for the .d and input .rs files.
40 // Those extra lines cause ninja warning:
41 // "warning: depfile has multiple output paths"
42 // For ninja, we keep/grep only the dependency rule for the rust $out file.
43 Deps: blueprint.DepsGCC,
44 Depfile: "$out.d",
45 },
Colin Cross004bd3f2023-10-02 11:39:17 -070046 "rustcFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
Wen-yi Chu41326c12023-09-22 03:58:59 +000047
48 _ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
49 rustdoc = pctx.AndroidStaticRule("rustdoc",
50 blueprint.RuleParams{
51 Command: "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
52 "touch $out",
53 CommandDeps: []string{"$rustdocCmd"},
54 },
55 "rustdocFlags", "outDir", "envVars")
56
57 _ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
58 clippyDriver = pctx.AndroidStaticRule("clippy",
59 blueprint.RuleParams{
60 Command: "$envVars $clippyCmd " +
61 // Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
62 // Use the metadata output as it has the smallest footprint.
63 "--emit metadata -o $out --emit dep-info=$out.d.raw $in ${libFlags} " +
64 "$rustcFlags $clippyFlags" +
Alex91c74762024-04-11 17:30:27 +020065 " && grep ^$out: $out.d.raw > $out.d",
Wen-yi Chu41326c12023-09-22 03:58:59 +000066 CommandDeps: []string{"$clippyCmd"},
67 Deps: blueprint.DepsGCC,
68 Depfile: "$out.d",
69 },
70 "rustcFlags", "libFlags", "clippyFlags", "envVars")
71
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -040072 zip = pctx.AndroidStaticRule("zip",
73 blueprint.RuleParams{
74 Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
75 CommandDeps: []string{"${SoongZipCmd}"},
76 Rspfile: "$out.rsp",
77 RspfileContent: "$in",
78 })
Ivan Lozano43845682020-07-09 21:03:28 -040079
Wen-yi Chu41326c12023-09-22 03:58:59 +000080 cp = pctx.AndroidStaticRule("cp",
Ivan Lozano43845682020-07-09 21:03:28 -040081 blueprint.RuleParams{
82 Command: "cp `cat $outDir.rsp` $outDir",
83 Rspfile: "${outDir}.rsp",
84 RspfileContent: "$in",
85 },
86 "outDir")
Sasha Smundaka76acba2022-04-18 20:12:56 -070087
88 // Cross-referencing:
89 _ = pctx.SourcePathVariable("rustExtractor",
90 "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/rust_extractor")
91 _ = pctx.VariableFunc("kytheCorpus",
92 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
93 _ = pctx.VariableFunc("kytheCuEncoding",
94 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
Wen-yi Chu41326c12023-09-22 03:58:59 +000095 _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
96 kytheExtract = pctx.AndroidStaticRule("kythe",
97 blueprint.RuleParams{
98 Command: `KYTHE_CORPUS=${kytheCorpus} ` +
99 `KYTHE_OUTPUT_FILE=$out ` +
100 `KYTHE_VNAMES=$kytheVnames ` +
101 `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
102 `KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
103 `$rustExtractor $envVars ` +
104 `$rustcCmd ` +
Ivan Lozanof4589012024-11-20 22:18:11 +0000105 `-C linker=${RustcLinkerCmd} ` +
106 `-C link-args="--android-clang-bin=${config.ClangCmd} ${crtBegin} ${linkFlags} ${crtEnd}" ` +
Wen-yi Chu41326c12023-09-22 03:58:59 +0000107 `$in ${libFlags} $rustcFlags`,
Ivan Lozanof4589012024-11-20 22:18:11 +0000108 CommandDeps: []string{"$rustExtractor", "$kytheVnames", "${RustcLinkerCmd}", "${config.ClangCmd}"},
Wen-yi Chu41326c12023-09-22 03:58:59 +0000109 Rspfile: "${out}.rsp",
110 RspfileContent: "$in",
111 },
Colin Cross004bd3f2023-10-02 11:39:17 -0700112 "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
Ivan Lozanoffee3342019-08-27 12:03:00 -0700113)
114
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400115type buildOutput struct {
Joel Galensonfa049382021-01-14 16:03:18 -0800116 outputFile android.Path
Sasha Smundaka76acba2022-04-18 20:12:56 -0700117 kytheFile android.Path
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400118}
Ivan Lozanoffee3342019-08-27 12:03:00 -0700119
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400120func init() {
121 pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
Ivan Lozanof4589012024-11-20 22:18:11 +0000122 pctx.HostBinToolVariable("RustcLinkerCmd", "rustc_linker")
Ivan Lozano0a468a42024-05-13 21:03:34 -0400123 cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
Ivan Lozanoffee3342019-08-27 12:03:00 -0700124}
125
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400126type transformProperties struct {
127 crateName string
128 targetTriple string
129 is64Bit bool
130 bootstrap bool
131 inRecovery bool
132 inRamdisk bool
133 inVendorRamdisk bool
134 cargoOutDir android.OptionalPath
135 synthetic bool
136 crateType string
137}
138
139// Populates a standard transformProperties struct for Rust modules
140func getTransformProperties(ctx ModuleContext, crateType string) transformProperties {
141 module := ctx.RustModule()
142 return transformProperties{
143 crateName: module.CrateName(),
144 is64Bit: ctx.toolchain().Is64Bit(),
145 targetTriple: ctx.toolchain().RustTriple(),
146 bootstrap: module.Bootstrap(),
147 inRecovery: module.InRecovery(),
148 inRamdisk: module.InRamdisk(),
149 inVendorRamdisk: module.InVendorRamdisk(),
150 cargoOutDir: module.compiler.cargoOutDir(),
151
152 // crateType indicates what type of crate to build
153 crateType: crateType,
154
155 // synthetic indicates whether this is an actual Rust module or not
156 synthetic: false,
157 }
158}
159
Wen-yi Chu41326c12023-09-22 03:58:59 +0000160func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700161 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400162 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700163}
164
Wen-yi Chu41326c12023-09-22 03:58:59 +0000165func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700166 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400167 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700168}
169
Ivan Lozano872e8462024-10-30 19:30:48 +0000170// TransformRlibstoStaticlib is assumed to be called from the cc module, and
171// thus needs to reconstruct the common set of flags which need to be passed
172// to the rustc compiler.
Ivan Lozano0a468a42024-05-13 21:03:34 -0400173func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
174 outputFile android.WritablePath) android.Path {
175
176 var rustPathDeps PathDeps
177 var rustFlags Flags
178
179 for _, rlibDep := range deps {
180 rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
181 rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
182 }
183
184 ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
185 toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
186 t := transformProperties{
187 // Crate name can be a predefined value as this is a staticlib and
188 // it does not need to be unique. The crate name is used for name
189 // mangling, but it is mixed with the metadata for that purpose, which we
190 // already set to the module name.
191 crateName: "generated_rust_staticlib",
192 is64Bit: toolchain.Is64Bit(),
193 targetTriple: toolchain.RustTriple(),
194 bootstrap: ccModule.Bootstrap(),
195 inRecovery: ccModule.InRecovery(),
196 inRamdisk: ccModule.InRamdisk(),
197 inVendorRamdisk: ccModule.InVendorRamdisk(),
198
199 // crateType indicates what type of crate to build
200 crateType: "staticlib",
201
202 // synthetic indicates whether this is an actual Rust module or not
203 synthetic: true,
204 }
205
206 rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
207 rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
Chris Wailesce48f5f2025-01-29 15:18:17 -0800208
209 if !ctx.Config().Eng() {
210 rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
211 }
Ivan Lozano0a468a42024-05-13 21:03:34 -0400212
213 rustFlags.EmitXrefs = false
214
215 return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
216}
217
Wen-yi Chu41326c12023-09-22 03:58:59 +0000218func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700219 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400220 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "dylib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700221}
222
Wen-yi Chu41326c12023-09-22 03:58:59 +0000223func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700224 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400225 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "staticlib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700226}
227
Wen-yi Chu41326c12023-09-22 03:58:59 +0000228func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700229 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400230 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "cdylib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700231}
232
Wen-yi Chu41326c12023-09-22 03:58:59 +0000233func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
Dan Albert06feee92021-03-19 15:06:02 -0700234 flags Flags, outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400235 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "proc-macro"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700236}
237
238func rustLibsToPaths(libs RustLibraries) android.Paths {
239 var paths android.Paths
240 for _, lib := range libs {
241 paths = append(paths, lib.Path)
242 }
243 return paths
244}
245
Wen-yi Chu41326c12023-09-22 03:58:59 +0000246func makeLibFlags(deps PathDeps) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700247 var libFlags []string
248
249 // Collect library/crate flags
Wen-yi Chu41326c12023-09-22 03:58:59 +0000250 for _, lib := range deps.RLibs {
251 libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700252 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000253 for _, lib := range deps.DyLibs {
Matthew Maurerf67d2112025-01-07 01:45:14 +0000254 libFlags = append(libFlags, "--extern force:"+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700255 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000256 for _, proc_macro := range deps.ProcMacros {
257 libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700258 }
259
260 for _, path := range deps.linkDirs {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000261 libFlags = append(libFlags, "-L "+path)
Dan Albert06feee92021-03-19 15:06:02 -0700262 }
263
264 return libFlags
265}
266
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400267func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700268 var envVars []string
269
270 // libstd requires a specific environment variable to be set. This is
271 // not officially documented and may be removed in the future. See
272 // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400273 if crateName == "std" {
274 envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
Dan Albert06feee92021-03-19 15:06:02 -0700275 }
276
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400277 if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
278 moduleGenDir := cargoOutDir
Dan Albert06feee92021-03-19 15:06:02 -0700279 // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
280 // assumes that paths are relative to the source file.
Wen-yi Chu41326c12023-09-22 03:58:59 +0000281 var outDirPrefix string
282 if !filepath.IsAbs(moduleGenDir.String()) {
Sam Delmericoa588d152023-06-16 10:28:04 -0400283 // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
Wen-yi Chu41326c12023-09-22 03:58:59 +0000284 outDirPrefix = "$$PWD/"
Sam Delmericoa588d152023-06-16 10:28:04 -0400285 } else {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000286 // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
287 outDirPrefix = ""
Dan Albert06feee92021-03-19 15:06:02 -0700288 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000289 envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
Peter Collingbourne0dcd62e2023-03-31 23:05:16 -0700290 } else {
291 // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
292 envVars = append(envVars, "OUT_DIR=out")
Dan Albert06feee92021-03-19 15:06:02 -0700293 }
294
Matthew Maurer34609fa2023-06-26 21:10:13 +0000295 envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
296
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400297 if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
298 // We only emulate cargo environment variables for 3p code, which is only ever built
299 // by defining a Rust module, so we only need to set these for true Rust modules.
300 if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
Matthew Maurer34609fa2023-06-26 21:10:13 +0000301 envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
302 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400303 envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
304 envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
305 pkgVersion := rustMod.compiler.cargoPkgVersion()
Matthew Maurer34609fa2023-06-26 21:10:13 +0000306 if pkgVersion != "" {
307 envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
Ivan Lozanof4455622023-07-28 12:42:20 -0400308
309 // Ensure the version is in the form of "x.y.z" (approximately semver compliant).
310 //
311 // For our purposes, we don't care to enforce that these are integers since they may
312 // include other characters at times (e.g. sometimes the patch version is more than an integer).
313 if strings.Count(pkgVersion, ".") == 2 {
314 var semver_parts = strings.Split(pkgVersion, ".")
315 envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
316 envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
317 envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
318 }
Matthew Maurer34609fa2023-06-26 21:10:13 +0000319 }
320 }
321
Sam Delmericoc5cf9902023-10-23 21:40:13 +0000322 if ctx.Darwin() {
323 envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
324 }
325
Dan Albert06feee92021-03-19 15:06:02 -0700326 return envVars
327}
328
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400329func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
330 outputFile android.WritablePath, t transformProperties) buildOutput {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700331
332 var inputs android.Paths
Colin Cross004bd3f2023-10-02 11:39:17 -0700333 var implicits android.Paths
334 var orderOnly android.Paths
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400335 var output buildOutput
Dan Albert06feee92021-03-19 15:06:02 -0700336 var rustcFlags, linkFlags []string
Wen-yi Chu41326c12023-09-22 03:58:59 +0000337 var earlyLinkFlags string
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400338
339 output.outputFile = outputFile
Ivan Lozanoffee3342019-08-27 12:03:00 -0700340
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400341 envVars := rustEnvVars(ctx, deps, t.crateName, t.cargoOutDir)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000342
Ivan Lozanoffee3342019-08-27 12:03:00 -0700343 inputs = append(inputs, main)
344
345 // Collect rustc flags
Ivan Lozanof1c84332019-09-20 11:00:37 -0700346 rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700347 rustcFlags = append(rustcFlags, flags.RustFlags...)
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400348 rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
349 if t.crateName != "" {
350 rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700351 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400352 if t.targetTriple != "" {
353 rustcFlags = append(rustcFlags, "--target="+t.targetTriple)
354 linkFlags = append(linkFlags, "-target "+t.targetTriple)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700355 }
Matthew Maurerbb3add12020-06-25 09:34:12 -0700356
357 // Suppress an implicit sysroot
358 rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
359
Chris Wailes99180c22024-02-20 21:39:40 +0000360 // Enable incremental compilation if requested by user
361 if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
362 incrementalPath := android.PathForOutput(ctx, "rustc").String()
363
364 rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
365 } else {
366 rustcFlags = append(rustcFlags, "-C codegen-units=1")
367 }
368
Chris Wailes6d12db42023-02-24 16:58:18 -0800369 // Disallow experimental features
Colin Crossf96b0012023-10-26 14:01:51 -0700370 modulePath := ctx.ModuleDir()
Chris Wailes6d12db42023-02-24 16:58:18 -0800371 if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
Chris Wailes547bfdd2023-05-31 11:53:44 -0700372 rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
Chris Wailesd9781fd2021-12-03 17:17:28 -0800373 }
374
Ivan Lozanof1c84332019-09-20 11:00:37 -0700375 // Collect linker flags
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700376 if !ctx.Darwin() {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000377 earlyLinkFlags = "-Wl,--as-needed"
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700378 }
379
Wen-yi Chu41326c12023-09-22 03:58:59 +0000380 linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
381 linkFlags = append(linkFlags, flags.LinkFlags...)
382
383 // Check if this module needs to use the bootstrap linker
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400384 if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000385 dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker"
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400386 if t.is64Bit {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000387 dynamicLinker += "64"
388 }
389 linkFlags = append(linkFlags, dynamicLinker)
390 }
391
392 libFlags := makeLibFlags(deps)
393
Ivan Lozanoffee3342019-08-27 12:03:00 -0700394 // Collect dependencies
Wen-yi Chu41326c12023-09-22 03:58:59 +0000395 implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
396 implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
397 implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700398 implicits = append(implicits, deps.StaticLibs...)
399 implicits = append(implicits, deps.SharedLibDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000400 implicits = append(implicits, deps.srcProviderFiles...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700401 implicits = append(implicits, deps.AfdoProfiles...)
Ivan Lozanof4589012024-11-20 22:18:11 +0000402 implicits = append(implicits, deps.LinkerDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000403
Colin Cross004bd3f2023-10-02 11:39:17 -0700404 implicits = append(implicits, deps.CrtBegin...)
405 implicits = append(implicits, deps.CrtEnd...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000406
Colin Cross004bd3f2023-10-02 11:39:17 -0700407 orderOnly = append(orderOnly, deps.SharedLibs...)
Sam Delmerico51d6d1c2023-03-28 16:54:00 -0400408
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400409 if !t.synthetic {
410 // Only worry about OUT_DIR for actual Rust modules.
411 // Libraries built from cc use generated source, and do not utilize OUT_DIR.
412 if len(deps.SrcDeps) > 0 {
413 var outputs android.WritablePaths
Ivan Lozano43845682020-07-09 21:03:28 -0400414
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400415 for _, genSrc := range deps.SrcDeps {
416 if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
417 ctx.PropertyErrorf("srcs",
418 "multiple source providers generate the same filename output: "+genSrc.Base())
419 }
420 outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
Ivan Lozano43845682020-07-09 21:03:28 -0400421 }
Ivan Lozano43845682020-07-09 21:03:28 -0400422
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400423 ctx.Build(pctx, android.BuildParams{
424 Rule: cp,
425 Description: "cp " + t.cargoOutDir.Path().Rel(),
426 Outputs: outputs,
427 Inputs: deps.SrcDeps,
428 Args: map[string]string{
429 "outDir": t.cargoOutDir.String(),
430 },
431 })
432 implicits = append(implicits, outputs.Paths()...)
433 }
Ivan Lozano43845682020-07-09 21:03:28 -0400434 }
435
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400436 if !t.synthetic {
437 // Only worry about clippy for actual Rust modules.
438 // Libraries built from cc use generated source, and don't need to run clippy.
439 if flags.Clippy {
440 clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
441 ctx.Build(pctx, android.BuildParams{
442 Rule: clippyDriver,
443 Description: "clippy " + main.Rel(),
444 Output: clippyFile,
445 ImplicitOutputs: nil,
446 Inputs: inputs,
447 Implicits: implicits,
448 OrderOnly: orderOnly,
449 Args: map[string]string{
450 "rustcFlags": strings.Join(rustcFlags, " "),
451 "libFlags": strings.Join(libFlags, " "),
452 "clippyFlags": strings.Join(flags.ClippyFlags, " "),
453 "envVars": strings.Join(envVars, " "),
454 },
455 })
456 // Declare the clippy build as an implicit dependency of the original crate.
457 implicits = append(implicits, clippyFile)
458 }
Ivan Lozanobae62be2020-07-21 13:28:27 -0400459 }
460
Wen-yi Chu41326c12023-09-22 03:58:59 +0000461 ctx.Build(pctx, android.BuildParams{
Colin Cross004bd3f2023-10-02 11:39:17 -0700462 Rule: rustc,
463 Description: "rustc " + main.Rel(),
464 Output: outputFile,
465 Inputs: inputs,
466 Implicits: implicits,
467 OrderOnly: orderOnly,
Wen-yi Chu41326c12023-09-22 03:58:59 +0000468 Args: map[string]string{
Colin Cross004bd3f2023-10-02 11:39:17 -0700469 "rustcFlags": strings.Join(rustcFlags, " "),
470 "earlyLinkFlags": earlyLinkFlags,
471 "linkFlags": strings.Join(linkFlags, " "),
472 "libFlags": strings.Join(libFlags, " "),
473 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
474 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
475 "envVars": strings.Join(envVars, " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000476 },
477 })
Ivan Lozanoffee3342019-08-27 12:03:00 -0700478
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400479 if !t.synthetic {
480 // Only emit xrefs for true Rust modules.
481 if flags.EmitXrefs {
482 kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
483 ctx.Build(pctx, android.BuildParams{
484 Rule: kytheExtract,
485 Description: "Xref Rust extractor " + main.Rel(),
486 Output: kytheFile,
487 Inputs: inputs,
488 Implicits: implicits,
489 OrderOnly: orderOnly,
490 Args: map[string]string{
491 "rustcFlags": strings.Join(rustcFlags, " "),
492 "linkFlags": strings.Join(linkFlags, " "),
493 "libFlags": strings.Join(libFlags, " "),
494 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
495 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
496 "envVars": strings.Join(envVars, " "),
497 },
498 })
499 output.kytheFile = kytheFile
500 }
Sasha Smundaka76acba2022-04-18 20:12:56 -0700501 }
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400502 return output
503}
Dan Albert06feee92021-03-19 15:06:02 -0700504
Wen-yi Chu41326c12023-09-22 03:58:59 +0000505func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
506 flags Flags) android.ModuleOutPath {
Dan Albert06feee92021-03-19 15:06:02 -0700507
508 rustdocFlags := append([]string{}, flags.RustdocFlags...)
509 rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
510
Dan Albertb433bf72021-04-27 17:12:02 -0700511 // Build an index for all our crates. -Z unstable options is required to use
512 // this flag.
513 rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
514
Chris Wailes3d211a02024-07-11 11:31:14 -0700515 // Ensure we use any special-case code-paths for Soong.
516 rustdocFlags = append(rustdocFlags, "--cfg", "soong")
517
Dan Albert06feee92021-03-19 15:06:02 -0700518 targetTriple := ctx.toolchain().RustTriple()
519
520 // Collect rustc flags
521 if targetTriple != "" {
522 rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
523 }
524
525 crateName := ctx.RustModule().CrateName()
Dan Albertb433bf72021-04-27 17:12:02 -0700526 rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
Dan Albert06feee92021-03-19 15:06:02 -0700527
Wen-yi Chu41326c12023-09-22 03:58:59 +0000528 rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
Dan Albert06feee92021-03-19 15:06:02 -0700529 docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
Dan Albertb433bf72021-04-27 17:12:02 -0700530
Chris Wailesb2703ad2021-07-30 13:25:42 -0700531 // Silence warnings about renamed lints for third-party crates
Colin Crossf96b0012023-10-26 14:01:51 -0700532 modulePath := ctx.ModuleDir()
Chris Wailesb2703ad2021-07-30 13:25:42 -0700533 if android.IsThirdPartyPath(modulePath) {
Chris Wailes7b3eb242023-02-14 16:09:49 -0800534 rustdocFlags = append(rustdocFlags, " -A warnings")
Chris Wailesb2703ad2021-07-30 13:25:42 -0700535 }
Chris Wailes9953a192021-07-28 12:07:16 -0700536
Dan Albertb433bf72021-04-27 17:12:02 -0700537 // Yes, the same out directory is used simultaneously by all rustdoc builds.
538 // This is what cargo does. The docs for individual crates get generated to
539 // a subdirectory named for the crate, and rustdoc synchronizes writes to
540 // shared pieces like the index and search data itself.
541 // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
542 docDir := android.PathForOutput(ctx, "rustdoc")
Dan Albert06feee92021-03-19 15:06:02 -0700543
Wen-yi Chu41326c12023-09-22 03:58:59 +0000544 ctx.Build(pctx, android.BuildParams{
545 Rule: rustdoc,
546 Description: "rustdoc " + main.Rel(),
547 Output: docTimestampFile,
548 Input: main,
549 Implicit: ctx.RustModule().UnstrippedOutputFile(),
550 Args: map[string]string{
551 "rustdocFlags": strings.Join(rustdocFlags, " "),
552 "outDir": docDir.String(),
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400553 "envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000554 },
555 })
Dan Albert06feee92021-03-19 15:06:02 -0700556
557 return docTimestampFile
558}