blob: 8a869aad847bd18b6d1154c13a619bad0a9d722f [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 {
Satish Yalla39834132025-01-30 20:59:55 -0800162 if ctx.RustModule().compiler.Thinlto() {
163 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
164 }
165
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400166 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "bin"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700167}
168
Wen-yi Chu41326c12023-09-22 03:58:59 +0000169func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700170 outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400171 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700172}
173
Ivan Lozano872e8462024-10-30 19:30:48 +0000174// TransformRlibstoStaticlib is assumed to be called from the cc module, and
175// thus needs to reconstruct the common set of flags which need to be passed
176// to the rustc compiler.
Ivan Lozano0a468a42024-05-13 21:03:34 -0400177func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
178 outputFile android.WritablePath) android.Path {
179
180 var rustPathDeps PathDeps
181 var rustFlags Flags
182
183 for _, rlibDep := range deps {
184 rustPathDeps.RLibs = append(rustPathDeps.RLibs, RustLibrary{Path: rlibDep.LibPath, CrateName: rlibDep.CrateName})
185 rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
186 }
187
188 ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
189 toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
190 t := transformProperties{
191 // Crate name can be a predefined value as this is a staticlib and
192 // it does not need to be unique. The crate name is used for name
193 // mangling, but it is mixed with the metadata for that purpose, which we
194 // already set to the module name.
195 crateName: "generated_rust_staticlib",
196 is64Bit: toolchain.Is64Bit(),
197 targetTriple: toolchain.RustTriple(),
198 bootstrap: ccModule.Bootstrap(),
199 inRecovery: ccModule.InRecovery(),
200 inRamdisk: ccModule.InRamdisk(),
201 inVendorRamdisk: ccModule.InVendorRamdisk(),
202
203 // crateType indicates what type of crate to build
204 crateType: "staticlib",
205
206 // synthetic indicates whether this is an actual Rust module or not
207 synthetic: true,
208 }
209
210 rustFlags = CommonDefaultFlags(ctx, toolchain, rustFlags)
211 rustFlags = CommonLibraryCompilerFlags(ctx, rustFlags)
Satish Yalla39834132025-01-30 20:59:55 -0800212 rustFlags.GlobalRustFlags = append(rustFlags.GlobalRustFlags, "-C lto=thin")
Ivan Lozano0a468a42024-05-13 21:03:34 -0400213
214 rustFlags.EmitXrefs = false
215
216 return transformSrctoCrate(ctx, mainSrc, rustPathDeps, rustFlags, outputFile, t).outputFile
217}
218
Wen-yi Chu41326c12023-09-22 03:58:59 +0000219func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700220 outputFile android.WritablePath) buildOutput {
Satish Yalla39834132025-01-30 20:59:55 -0800221 if ctx.RustModule().compiler.Thinlto() {
222 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
223 }
224
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400225 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "dylib"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700226}
227
Wen-yi Chu41326c12023-09-22 03:58:59 +0000228func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700229 outputFile android.WritablePath) buildOutput {
Satish Yalla39834132025-01-30 20:59:55 -0800230 if ctx.RustModule().compiler.Thinlto() {
231 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
232 }
233
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400234 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "staticlib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700235}
236
Wen-yi Chu41326c12023-09-22 03:58:59 +0000237func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
Dan Albert06feee92021-03-19 15:06:02 -0700238 outputFile android.WritablePath) buildOutput {
Satish Yalla39834132025-01-30 20:59:55 -0800239 if ctx.RustModule().compiler.Thinlto() {
240 flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
241 }
242
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400243 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "cdylib"))
Ivan Lozano52767be2019-10-18 14:49:46 -0700244}
245
Wen-yi Chu41326c12023-09-22 03:58:59 +0000246func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
Dan Albert06feee92021-03-19 15:06:02 -0700247 flags Flags, outputFile android.WritablePath) buildOutput {
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400248 return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "proc-macro"))
Ivan Lozanoffee3342019-08-27 12:03:00 -0700249}
250
251func rustLibsToPaths(libs RustLibraries) android.Paths {
252 var paths android.Paths
253 for _, lib := range libs {
254 paths = append(paths, lib.Path)
255 }
256 return paths
257}
258
Wen-yi Chu41326c12023-09-22 03:58:59 +0000259func makeLibFlags(deps PathDeps) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700260 var libFlags []string
261
262 // Collect library/crate flags
Wen-yi Chu41326c12023-09-22 03:58:59 +0000263 for _, lib := range deps.RLibs {
264 libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700265 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000266 for _, lib := range deps.DyLibs {
Matthew Maurerf67d2112025-01-07 01:45:14 +0000267 libFlags = append(libFlags, "--extern force:"+lib.CrateName+"="+lib.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700268 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000269 for _, proc_macro := range deps.ProcMacros {
270 libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
Dan Albert06feee92021-03-19 15:06:02 -0700271 }
272
273 for _, path := range deps.linkDirs {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000274 libFlags = append(libFlags, "-L "+path)
Dan Albert06feee92021-03-19 15:06:02 -0700275 }
276
277 return libFlags
278}
279
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400280func rustEnvVars(ctx android.ModuleContext, deps PathDeps, crateName string, cargoOutDir android.OptionalPath) []string {
Dan Albert06feee92021-03-19 15:06:02 -0700281 var envVars []string
282
283 // libstd requires a specific environment variable to be set. This is
284 // not officially documented and may be removed in the future. See
285 // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400286 if crateName == "std" {
287 envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.Arch().ArchType])
Dan Albert06feee92021-03-19 15:06:02 -0700288 }
289
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400290 if len(deps.SrcDeps) > 0 && cargoOutDir.Valid() {
291 moduleGenDir := cargoOutDir
Dan Albert06feee92021-03-19 15:06:02 -0700292 // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
293 // assumes that paths are relative to the source file.
Wen-yi Chu41326c12023-09-22 03:58:59 +0000294 var outDirPrefix string
295 if !filepath.IsAbs(moduleGenDir.String()) {
Sam Delmericoa588d152023-06-16 10:28:04 -0400296 // 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 +0000297 outDirPrefix = "$$PWD/"
Sam Delmericoa588d152023-06-16 10:28:04 -0400298 } else {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000299 // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
300 outDirPrefix = ""
Dan Albert06feee92021-03-19 15:06:02 -0700301 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000302 envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
Peter Collingbourne0dcd62e2023-03-31 23:05:16 -0700303 } else {
304 // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
305 envVars = append(envVars, "OUT_DIR=out")
Dan Albert06feee92021-03-19 15:06:02 -0700306 }
307
Matthew Maurer34609fa2023-06-26 21:10:13 +0000308 envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
309
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400310 if rustMod, ok := ctx.Module().(*Module); ok && rustMod.compiler.cargoEnvCompat() {
311 // We only emulate cargo environment variables for 3p code, which is only ever built
312 // by defining a Rust module, so we only need to set these for true Rust modules.
313 if bin, ok := rustMod.compiler.(*binaryDecorator); ok {
Matthew Maurer34609fa2023-06-26 21:10:13 +0000314 envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
315 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400316 envVars = append(envVars, "CARGO_CRATE_NAME="+crateName)
317 envVars = append(envVars, "CARGO_PKG_NAME="+crateName)
318 pkgVersion := rustMod.compiler.cargoPkgVersion()
Matthew Maurer34609fa2023-06-26 21:10:13 +0000319 if pkgVersion != "" {
320 envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
Ivan Lozanof4455622023-07-28 12:42:20 -0400321
322 // Ensure the version is in the form of "x.y.z" (approximately semver compliant).
323 //
324 // For our purposes, we don't care to enforce that these are integers since they may
325 // include other characters at times (e.g. sometimes the patch version is more than an integer).
326 if strings.Count(pkgVersion, ".") == 2 {
327 var semver_parts = strings.Split(pkgVersion, ".")
328 envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
329 envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
330 envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
331 }
Matthew Maurer34609fa2023-06-26 21:10:13 +0000332 }
333 }
334
Sam Delmericoc5cf9902023-10-23 21:40:13 +0000335 if ctx.Darwin() {
336 envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
337 }
338
Dan Albert06feee92021-03-19 15:06:02 -0700339 return envVars
340}
341
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400342func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps PathDeps, flags Flags,
343 outputFile android.WritablePath, t transformProperties) buildOutput {
Ivan Lozanoffee3342019-08-27 12:03:00 -0700344
345 var inputs android.Paths
Colin Cross004bd3f2023-10-02 11:39:17 -0700346 var implicits android.Paths
347 var orderOnly android.Paths
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400348 var output buildOutput
Dan Albert06feee92021-03-19 15:06:02 -0700349 var rustcFlags, linkFlags []string
Wen-yi Chu41326c12023-09-22 03:58:59 +0000350 var earlyLinkFlags string
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400351
352 output.outputFile = outputFile
Ivan Lozanoffee3342019-08-27 12:03:00 -0700353
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400354 envVars := rustEnvVars(ctx, deps, t.crateName, t.cargoOutDir)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000355
Ivan Lozanoffee3342019-08-27 12:03:00 -0700356 inputs = append(inputs, main)
357
358 // Collect rustc flags
Ivan Lozanof1c84332019-09-20 11:00:37 -0700359 rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700360 rustcFlags = append(rustcFlags, flags.RustFlags...)
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400361 rustcFlags = append(rustcFlags, "--crate-type="+t.crateType)
362 if t.crateName != "" {
363 rustcFlags = append(rustcFlags, "--crate-name="+t.crateName)
Ivan Lozanoad8b18b2019-10-31 19:38:29 -0700364 }
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400365 if t.targetTriple != "" {
366 rustcFlags = append(rustcFlags, "--target="+t.targetTriple)
367 linkFlags = append(linkFlags, "-target "+t.targetTriple)
Ivan Lozanoffee3342019-08-27 12:03:00 -0700368 }
Matthew Maurerbb3add12020-06-25 09:34:12 -0700369
370 // Suppress an implicit sysroot
371 rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
372
Chris Wailes99180c22024-02-20 21:39:40 +0000373 // Enable incremental compilation if requested by user
374 if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
375 incrementalPath := android.PathForOutput(ctx, "rustc").String()
376
377 rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
378 } else {
379 rustcFlags = append(rustcFlags, "-C codegen-units=1")
380 }
381
Chris Wailes6d12db42023-02-24 16:58:18 -0800382 // Disallow experimental features
Colin Crossf96b0012023-10-26 14:01:51 -0700383 modulePath := ctx.ModuleDir()
Chris Wailes6d12db42023-02-24 16:58:18 -0800384 if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
Chris Wailes547bfdd2023-05-31 11:53:44 -0700385 rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
Chris Wailesd9781fd2021-12-03 17:17:28 -0800386 }
387
Ivan Lozanof1c84332019-09-20 11:00:37 -0700388 // Collect linker flags
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700389 if !ctx.Darwin() {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000390 earlyLinkFlags = "-Wl,--as-needed"
A. Cody Schuffelenf29ca582023-07-13 19:03:39 -0700391 }
392
Wen-yi Chu41326c12023-09-22 03:58:59 +0000393 linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
394 linkFlags = append(linkFlags, flags.LinkFlags...)
395
396 // Check if this module needs to use the bootstrap linker
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400397 if t.bootstrap && !t.inRecovery && !t.inRamdisk && !t.inVendorRamdisk {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000398 dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker"
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400399 if t.is64Bit {
Wen-yi Chu41326c12023-09-22 03:58:59 +0000400 dynamicLinker += "64"
401 }
402 linkFlags = append(linkFlags, dynamicLinker)
403 }
404
405 libFlags := makeLibFlags(deps)
406
Ivan Lozanoffee3342019-08-27 12:03:00 -0700407 // Collect dependencies
Wen-yi Chu41326c12023-09-22 03:58:59 +0000408 implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
409 implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
410 implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700411 implicits = append(implicits, deps.StaticLibs...)
412 implicits = append(implicits, deps.SharedLibDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000413 implicits = append(implicits, deps.srcProviderFiles...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700414 implicits = append(implicits, deps.AfdoProfiles...)
Ivan Lozanof4589012024-11-20 22:18:11 +0000415 implicits = append(implicits, deps.LinkerDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000416
Colin Cross004bd3f2023-10-02 11:39:17 -0700417 implicits = append(implicits, deps.CrtBegin...)
418 implicits = append(implicits, deps.CrtEnd...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000419
Colin Cross004bd3f2023-10-02 11:39:17 -0700420 orderOnly = append(orderOnly, deps.SharedLibs...)
Sam Delmerico51d6d1c2023-03-28 16:54:00 -0400421
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400422 if !t.synthetic {
423 // Only worry about OUT_DIR for actual Rust modules.
424 // Libraries built from cc use generated source, and do not utilize OUT_DIR.
425 if len(deps.SrcDeps) > 0 {
426 var outputs android.WritablePaths
Ivan Lozano43845682020-07-09 21:03:28 -0400427
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400428 for _, genSrc := range deps.SrcDeps {
429 if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
430 ctx.PropertyErrorf("srcs",
431 "multiple source providers generate the same filename output: "+genSrc.Base())
432 }
433 outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
Ivan Lozano43845682020-07-09 21:03:28 -0400434 }
Ivan Lozano43845682020-07-09 21:03:28 -0400435
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400436 ctx.Build(pctx, android.BuildParams{
437 Rule: cp,
438 Description: "cp " + t.cargoOutDir.Path().Rel(),
439 Outputs: outputs,
440 Inputs: deps.SrcDeps,
441 Args: map[string]string{
442 "outDir": t.cargoOutDir.String(),
443 },
444 })
445 implicits = append(implicits, outputs.Paths()...)
446 }
Ivan Lozano43845682020-07-09 21:03:28 -0400447 }
448
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400449 if !t.synthetic {
450 // Only worry about clippy for actual Rust modules.
451 // Libraries built from cc use generated source, and don't need to run clippy.
452 if flags.Clippy {
453 clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
454 ctx.Build(pctx, android.BuildParams{
455 Rule: clippyDriver,
456 Description: "clippy " + main.Rel(),
457 Output: clippyFile,
458 ImplicitOutputs: nil,
459 Inputs: inputs,
460 Implicits: implicits,
461 OrderOnly: orderOnly,
462 Args: map[string]string{
463 "rustcFlags": strings.Join(rustcFlags, " "),
464 "libFlags": strings.Join(libFlags, " "),
465 "clippyFlags": strings.Join(flags.ClippyFlags, " "),
466 "envVars": strings.Join(envVars, " "),
467 },
468 })
469 // Declare the clippy build as an implicit dependency of the original crate.
470 implicits = append(implicits, clippyFile)
471 }
Ivan Lozanobae62be2020-07-21 13:28:27 -0400472 }
473
Wen-yi Chu41326c12023-09-22 03:58:59 +0000474 ctx.Build(pctx, android.BuildParams{
Colin Cross004bd3f2023-10-02 11:39:17 -0700475 Rule: rustc,
476 Description: "rustc " + main.Rel(),
477 Output: outputFile,
478 Inputs: inputs,
479 Implicits: implicits,
480 OrderOnly: orderOnly,
Wen-yi Chu41326c12023-09-22 03:58:59 +0000481 Args: map[string]string{
Colin Cross004bd3f2023-10-02 11:39:17 -0700482 "rustcFlags": strings.Join(rustcFlags, " "),
483 "earlyLinkFlags": earlyLinkFlags,
484 "linkFlags": strings.Join(linkFlags, " "),
485 "libFlags": strings.Join(libFlags, " "),
486 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
487 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
488 "envVars": strings.Join(envVars, " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000489 },
490 })
Ivan Lozanoffee3342019-08-27 12:03:00 -0700491
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400492 if !t.synthetic {
493 // Only emit xrefs for true Rust modules.
494 if flags.EmitXrefs {
495 kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
496 ctx.Build(pctx, android.BuildParams{
497 Rule: kytheExtract,
498 Description: "Xref Rust extractor " + main.Rel(),
499 Output: kytheFile,
500 Inputs: inputs,
501 Implicits: implicits,
502 OrderOnly: orderOnly,
503 Args: map[string]string{
504 "rustcFlags": strings.Join(rustcFlags, " "),
505 "linkFlags": strings.Join(linkFlags, " "),
506 "libFlags": strings.Join(libFlags, " "),
507 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
508 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
509 "envVars": strings.Join(envVars, " "),
510 },
511 })
512 output.kytheFile = kytheFile
513 }
Sasha Smundaka76acba2022-04-18 20:12:56 -0700514 }
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400515 return output
516}
Dan Albert06feee92021-03-19 15:06:02 -0700517
Wen-yi Chu41326c12023-09-22 03:58:59 +0000518func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
519 flags Flags) android.ModuleOutPath {
Dan Albert06feee92021-03-19 15:06:02 -0700520
521 rustdocFlags := append([]string{}, flags.RustdocFlags...)
522 rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
523
Dan Albertb433bf72021-04-27 17:12:02 -0700524 // Build an index for all our crates. -Z unstable options is required to use
525 // this flag.
526 rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
527
Chris Wailes3d211a02024-07-11 11:31:14 -0700528 // Ensure we use any special-case code-paths for Soong.
529 rustdocFlags = append(rustdocFlags, "--cfg", "soong")
530
Dan Albert06feee92021-03-19 15:06:02 -0700531 targetTriple := ctx.toolchain().RustTriple()
532
533 // Collect rustc flags
534 if targetTriple != "" {
535 rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
536 }
537
538 crateName := ctx.RustModule().CrateName()
Dan Albertb433bf72021-04-27 17:12:02 -0700539 rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
Dan Albert06feee92021-03-19 15:06:02 -0700540
Wen-yi Chu41326c12023-09-22 03:58:59 +0000541 rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
Dan Albert06feee92021-03-19 15:06:02 -0700542 docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
Dan Albertb433bf72021-04-27 17:12:02 -0700543
Chris Wailesb2703ad2021-07-30 13:25:42 -0700544 // Silence warnings about renamed lints for third-party crates
Colin Crossf96b0012023-10-26 14:01:51 -0700545 modulePath := ctx.ModuleDir()
Chris Wailesb2703ad2021-07-30 13:25:42 -0700546 if android.IsThirdPartyPath(modulePath) {
Chris Wailes7b3eb242023-02-14 16:09:49 -0800547 rustdocFlags = append(rustdocFlags, " -A warnings")
Chris Wailesb2703ad2021-07-30 13:25:42 -0700548 }
Chris Wailes9953a192021-07-28 12:07:16 -0700549
Dan Albertb433bf72021-04-27 17:12:02 -0700550 // Yes, the same out directory is used simultaneously by all rustdoc builds.
551 // This is what cargo does. The docs for individual crates get generated to
552 // a subdirectory named for the crate, and rustdoc synchronizes writes to
553 // shared pieces like the index and search data itself.
554 // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
555 docDir := android.PathForOutput(ctx, "rustdoc")
Dan Albert06feee92021-03-19 15:06:02 -0700556
Wen-yi Chu41326c12023-09-22 03:58:59 +0000557 ctx.Build(pctx, android.BuildParams{
558 Rule: rustdoc,
559 Description: "rustdoc " + main.Rel(),
560 Output: docTimestampFile,
561 Input: main,
562 Implicit: ctx.RustModule().UnstrippedOutputFile(),
563 Args: map[string]string{
564 "rustdocFlags": strings.Join(rustdocFlags, " "),
565 "outDir": docDir.String(),
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400566 "envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000567 },
568 })
Dan Albert06feee92021-03-19 15:06:02 -0700569
570 return docTimestampFile
571}