blob: 1b6a6c117d15c8c840743c5da8bf6e8a51dab3ca [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 Lozano85f00cf2025-02-11 20:19:19 +0000174// TransformRlibstoStaticlib is assumed to be callable from the cc module, and
Ivan Lozano872e8462024-10-30 19:30:48 +0000175// 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
Ivan Lozano85f00cf2025-02-11 20:19:19 +0000188 mod := ctx.Module().(cc.LinkableInterface)
Ivan Lozano0a468a42024-05-13 21:03:34 -0400189 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(),
Ivan Lozano85f00cf2025-02-11 20:19:19 +0000198 bootstrap: mod.Bootstrap(),
199 inRecovery: mod.InRecovery(),
200 inRamdisk: mod.InRamdisk(),
201 inVendorRamdisk: mod.InVendorRamdisk(),
Ivan Lozano0a468a42024-05-13 21:03:34 -0400202
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
Ivan Lozano85f00cf2025-02-11 20:19:19 +0000405 if generatedLib := cc.GenerateRustStaticlib(ctx, deps.ccRlibDeps); generatedLib != nil {
406 deps.StaticLibs = append(deps.StaticLibs, generatedLib)
407 linkFlags = append(linkFlags, generatedLib.String())
408 }
409
Wen-yi Chu41326c12023-09-22 03:58:59 +0000410 libFlags := makeLibFlags(deps)
411
Ivan Lozanoffee3342019-08-27 12:03:00 -0700412 // Collect dependencies
Wen-yi Chu41326c12023-09-22 03:58:59 +0000413 implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
414 implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
415 implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700416 implicits = append(implicits, deps.StaticLibs...)
417 implicits = append(implicits, deps.SharedLibDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000418 implicits = append(implicits, deps.srcProviderFiles...)
Colin Cross004bd3f2023-10-02 11:39:17 -0700419 implicits = append(implicits, deps.AfdoProfiles...)
Ivan Lozanof4589012024-11-20 22:18:11 +0000420 implicits = append(implicits, deps.LinkerDeps...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000421
Colin Cross004bd3f2023-10-02 11:39:17 -0700422 implicits = append(implicits, deps.CrtBegin...)
423 implicits = append(implicits, deps.CrtEnd...)
Wen-yi Chu41326c12023-09-22 03:58:59 +0000424
Colin Cross004bd3f2023-10-02 11:39:17 -0700425 orderOnly = append(orderOnly, deps.SharedLibs...)
Sam Delmerico51d6d1c2023-03-28 16:54:00 -0400426
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400427 if !t.synthetic {
428 // Only worry about OUT_DIR for actual Rust modules.
429 // Libraries built from cc use generated source, and do not utilize OUT_DIR.
430 if len(deps.SrcDeps) > 0 {
431 var outputs android.WritablePaths
Ivan Lozano43845682020-07-09 21:03:28 -0400432
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400433 for _, genSrc := range deps.SrcDeps {
434 if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
435 ctx.PropertyErrorf("srcs",
436 "multiple source providers generate the same filename output: "+genSrc.Base())
437 }
438 outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
Ivan Lozano43845682020-07-09 21:03:28 -0400439 }
Ivan Lozano43845682020-07-09 21:03:28 -0400440
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400441 ctx.Build(pctx, android.BuildParams{
442 Rule: cp,
443 Description: "cp " + t.cargoOutDir.Path().Rel(),
444 Outputs: outputs,
445 Inputs: deps.SrcDeps,
446 Args: map[string]string{
447 "outDir": t.cargoOutDir.String(),
448 },
449 })
450 implicits = append(implicits, outputs.Paths()...)
451 }
Ivan Lozano43845682020-07-09 21:03:28 -0400452 }
453
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400454 if !t.synthetic {
455 // Only worry about clippy for actual Rust modules.
456 // Libraries built from cc use generated source, and don't need to run clippy.
457 if flags.Clippy {
458 clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
459 ctx.Build(pctx, android.BuildParams{
460 Rule: clippyDriver,
461 Description: "clippy " + main.Rel(),
462 Output: clippyFile,
463 ImplicitOutputs: nil,
464 Inputs: inputs,
465 Implicits: implicits,
466 OrderOnly: orderOnly,
467 Args: map[string]string{
468 "rustcFlags": strings.Join(rustcFlags, " "),
469 "libFlags": strings.Join(libFlags, " "),
470 "clippyFlags": strings.Join(flags.ClippyFlags, " "),
471 "envVars": strings.Join(envVars, " "),
472 },
473 })
474 // Declare the clippy build as an implicit dependency of the original crate.
475 implicits = append(implicits, clippyFile)
476 }
Ivan Lozanobae62be2020-07-21 13:28:27 -0400477 }
478
Wen-yi Chu41326c12023-09-22 03:58:59 +0000479 ctx.Build(pctx, android.BuildParams{
Colin Cross004bd3f2023-10-02 11:39:17 -0700480 Rule: rustc,
481 Description: "rustc " + main.Rel(),
482 Output: outputFile,
483 Inputs: inputs,
484 Implicits: implicits,
485 OrderOnly: orderOnly,
Wen-yi Chu41326c12023-09-22 03:58:59 +0000486 Args: map[string]string{
Colin Cross004bd3f2023-10-02 11:39:17 -0700487 "rustcFlags": strings.Join(rustcFlags, " "),
488 "earlyLinkFlags": earlyLinkFlags,
489 "linkFlags": strings.Join(linkFlags, " "),
490 "libFlags": strings.Join(libFlags, " "),
491 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
492 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
493 "envVars": strings.Join(envVars, " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000494 },
495 })
Ivan Lozanoffee3342019-08-27 12:03:00 -0700496
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400497 if !t.synthetic {
498 // Only emit xrefs for true Rust modules.
499 if flags.EmitXrefs {
500 kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
501 ctx.Build(pctx, android.BuildParams{
502 Rule: kytheExtract,
503 Description: "Xref Rust extractor " + main.Rel(),
504 Output: kytheFile,
505 Inputs: inputs,
506 Implicits: implicits,
507 OrderOnly: orderOnly,
508 Args: map[string]string{
509 "rustcFlags": strings.Join(rustcFlags, " "),
510 "linkFlags": strings.Join(linkFlags, " "),
511 "libFlags": strings.Join(libFlags, " "),
512 "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
513 "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
514 "envVars": strings.Join(envVars, " "),
515 },
516 })
517 output.kytheFile = kytheFile
518 }
Sasha Smundaka76acba2022-04-18 20:12:56 -0700519 }
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -0400520 return output
521}
Dan Albert06feee92021-03-19 15:06:02 -0700522
Wen-yi Chu41326c12023-09-22 03:58:59 +0000523func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
524 flags Flags) android.ModuleOutPath {
Dan Albert06feee92021-03-19 15:06:02 -0700525
526 rustdocFlags := append([]string{}, flags.RustdocFlags...)
527 rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
528
Dan Albertb433bf72021-04-27 17:12:02 -0700529 // Build an index for all our crates. -Z unstable options is required to use
530 // this flag.
531 rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
532
Chris Wailes3d211a02024-07-11 11:31:14 -0700533 // Ensure we use any special-case code-paths for Soong.
534 rustdocFlags = append(rustdocFlags, "--cfg", "soong")
535
Dan Albert06feee92021-03-19 15:06:02 -0700536 targetTriple := ctx.toolchain().RustTriple()
537
538 // Collect rustc flags
539 if targetTriple != "" {
540 rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
541 }
542
543 crateName := ctx.RustModule().CrateName()
Dan Albertb433bf72021-04-27 17:12:02 -0700544 rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
Dan Albert06feee92021-03-19 15:06:02 -0700545
Wen-yi Chu41326c12023-09-22 03:58:59 +0000546 rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
Dan Albert06feee92021-03-19 15:06:02 -0700547 docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
Dan Albertb433bf72021-04-27 17:12:02 -0700548
Chris Wailesb2703ad2021-07-30 13:25:42 -0700549 // Silence warnings about renamed lints for third-party crates
Colin Crossf96b0012023-10-26 14:01:51 -0700550 modulePath := ctx.ModuleDir()
Chris Wailesb2703ad2021-07-30 13:25:42 -0700551 if android.IsThirdPartyPath(modulePath) {
Chris Wailes7b3eb242023-02-14 16:09:49 -0800552 rustdocFlags = append(rustdocFlags, " -A warnings")
Chris Wailesb2703ad2021-07-30 13:25:42 -0700553 }
Chris Wailes9953a192021-07-28 12:07:16 -0700554
Dan Albertb433bf72021-04-27 17:12:02 -0700555 // Yes, the same out directory is used simultaneously by all rustdoc builds.
556 // This is what cargo does. The docs for individual crates get generated to
557 // a subdirectory named for the crate, and rustdoc synchronizes writes to
558 // shared pieces like the index and search data itself.
559 // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
560 docDir := android.PathForOutput(ctx, "rustdoc")
Dan Albert06feee92021-03-19 15:06:02 -0700561
Wen-yi Chu41326c12023-09-22 03:58:59 +0000562 ctx.Build(pctx, android.BuildParams{
563 Rule: rustdoc,
564 Description: "rustdoc " + main.Rel(),
565 Output: docTimestampFile,
566 Input: main,
567 Implicit: ctx.RustModule().UnstrippedOutputFile(),
568 Args: map[string]string{
569 "rustdocFlags": strings.Join(rustdocFlags, " "),
570 "outDir": docDir.String(),
Ivan Lozano28ed8f42024-05-06 21:46:39 -0400571 "envVars": strings.Join(rustEnvVars(ctx, deps, crateName, ctx.RustModule().compiler.cargoOutDir()), " "),
Wen-yi Chu41326c12023-09-22 03:58:59 +0000572 },
573 })
Dan Albert06feee92021-03-19 15:06:02 -0700574
575 return docTimestampFile
576}